-- local Util = require("lazyvim.util")
local lualine_colors = {
	cyan = "#79dac8",
	black = "#080808",
	white = "#c6c6c6",
	red = "#ff5189",
	-- blue   = '#80a0ff',
	-- violet = '#d183e8',
	-- grey   = '#303030',
	blue = "#d183e8",
	violet = "#77aafa",
	grey = "#2c2c3c",
}
local bubbles_theme = {
	normal = {
		a = { fg = lualine_colors.black, bg = lualine_colors.violet },
		b = { fg = lualine_colors.white, bg = lualine_colors.grey },
		c = { fg = lualine_colors.white },
	},
	insert = { a = { fg = lualine_colors.black, bg = lualine_colors.blue } },
	visual = { a = { fg = lualine_colors.black, bg = lualine_colors.cyan } },
	replace = { a = { fg = lualine_colors.black, bg = lualine_colors.red } },
	inactive = {
		a = { fg = lualine_colors.white, bg = lualine_colors.black },
		b = { fg = lualine_colors.white, bg = lualine_colors.black },
		c = { fg = lualine_colors.white },
	},
}

local function isempty(s)
	return s == nil or s == ""
end
local function use_if_defined(val, fallback)
	return val ~= nil and val or fallback
end
local conda_prefix = os.getenv("CONDA_PREFIX")
if not isempty(conda_prefix) then
	vim.g.python_host_prog = use_if_defined(vim.g.python_host_prog, conda_prefix .. "/bin/python")
	vim.g.python3_host_prog = use_if_defined(vim.g.python3_host_prog, conda_prefix .. "/bin/python")
else
	vim.g.python_host_prog = use_if_defined(vim.g.python_host_prog, "python")
	vim.g.python3_host_prog = use_if_defined(vim.g.python3_host_prog, "python3")
end

local function sd_get_char_at_position(line, column)
	local buffer = vim.api.nvim_get_current_buf()
	local line_text = vim.api.nvim_buf_get_lines(buffer, line - 1, line, false)

	if column <= #line_text[1] then
		return string.sub(line_text[1], column, column)
	else
		return nil
	end
end

local function sd_get_cursor_char()
	local l, c = unpack(vim.api.nvim_win_get_cursor(0))
	return sd_get_char_at_position(l, c + 1)
end

local function sd_get_continuous_chars_under_cursor()
	local line = vim.api.nvim_get_current_line()
	local col = vim.api.nvim_win_get_cursor(0)[2] + 1 -- Adjust for 0-based indexing

	if sd_get_cursor_char():match("%s") then
		vim.api.nvim_command("normal! w")
	end
	while not sd_get_cursor_char():match("[%a%d-_/%.~]") do
		vim.api.nvim_command("normal! l")
		local l, c = unpack(vim.api.nvim_win_get_cursor(0))
		if c + 1 == col then
			vim.api.nvim_command("normal! b")
		end
	end

	col = vim.api.nvim_win_get_cursor(0)[2] + 1 -- Adjust for 0-based indexing
	local start_col = col

	-- Iterate backwards to find the start of the continuous character sequence
	while start_col > 1 and line:sub(start_col - 1, start_col - 1):match("[%a%d-_/%.~]") do
		start_col = start_col - 1
	end

	-- Iterate forwards to find the end of the continuous character sequence
	local end_col = col
	while end_col <= #line and line:sub(end_col, end_col):match("[%a%d-_/%.]") do
		end_col = end_col + 1
	end
	-- print(end_col)

	-- Extract the continuous character sequence
	local chars = line:sub(start_col, end_col - 1)

	-- print(chars)
	return chars
end

-- !!! disable autoformat
vim.g.autoformat = false

-- local lazyterm = function() LazyVim.terminal(nil, { cwd = LazyVim.root() }) end
local function Rooter()
	local current_dir = LazyVim.root()
	vim.cmd("lcd " .. current_dir)
	print("Changed directory to: " .. current_dir)
end
-- Expose the change_dir function as a Neovim command
vim.api.nvim_create_user_command("Rooter", Rooter, {})

-- !!! plugins
return {

	{
		"Exafunction/codeium.nvim",
		command = { "Codeium Auth", "Codeium Chat" },
		-- ft = { "py", "go", "js", "sh" },
		event = "InsertEnter",
		enabled = function()
			return vim.g.hostname == "apple"
		end,
		-- lazy = false,
		dependencies = {
			"nvim-lua/plenary.nvim",
			"hrsh7th/nvim-cmp",
		},
		config = function()
			require("codeium").setup({
				detect_proxy = true,
				enable_chat = false,
				-- config_path = "",
				-- bin_path = "",
			})
		end,
	},

	{
		"ellisonleao/gruvbox.nvim",
		priority = 1000,
		config = true,
		enabled = function()
			return not (vim.g.hostname == "apple")
		end,
	},

	{
		"LazyVim/LazyVim",
		opts = {
			-- !!# do not remove line here
			-- colorscheme = "gruvbox",
			colorscheme = "gruvbox",
		},
	},

	{
		"folke/snacks.nvim",
		priority = 1000,
		lazy = false,
		opts = {
			git = { enable = false },
			gitbrowse = { enable = false },
			debug = { enable = false },
			bufdelete = { enable = false },
			lazygit = { enable = false },
			toggle = { enable = false },
			win = { enable = false },
			bigfile = {
				enabled = true,
				notify = true, -- show notification when big file detected
				size = 1.5 * 1024 * 1024, -- 1.5MB
				setup = function(ctx)
					vim.b.minianimate_disable = true
					vim.schedule(function()
						vim.bo[ctx.buf].syntax = ctx.ft
					end)
				end,
			},
			notifier = {
				enabled = true,
				timeout = 3000,
			},
			quickfile = { enabled = true },
			statuscolumn = {
				enabled = false,
				left = { "mark" }, -- priority of signs on the left (high to low)
				right = { "sign" }, -- priority of signs on the left (high to low)
				folds = {
					open = false, -- show open fold icons
					git_hl = false, -- use Git Signs hl for fold icons
				},
				git = {
					-- patterns to match Git signs
					patterns = { "GitSign", "MiniDiffSign" },
				},
				refresh = 50, -- refresh at most every 50ms
			},
			words = { enabled = false },
			styles = {
				notification = {
					wo = { wrap = true }, -- Wrap notifications
				},
			},
			dashboard = {
				preset = {
					pick = nil, -- "fzf-lua"
					keys = {
						{
							icon = " ",
							key = "f",
							desc = "Find File",
							action = ":lua Snacks.dashboard.pick('files')",
						},
						{ icon = " ", key = "n", desc = "New File", action = ":ene | startinsert" },
						{
							icon = " ",
							key = "g",
							desc = "Find Text",
							action = ":lua Snacks.dashboard.pick('live_grep')",
						},
						{
							icon = " ",
							key = "r",
							desc = "Recent Files",
							action = ":lua Snacks.dashboard.pick('oldfiles')",
						},
						{
							icon = " ",
							key = "c",
							desc = "Config",
							action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})",
						},
						{
							icon = " ",
							key = "s",
							desc = "Restore Session",
							action = ":call Sd_session_management('load')",
						},
						{
							icon = " ",
							key = "l",
							desc = "Restore Session",
							action = ":call Sd_restore_last_session()",
						},
						{
							icon = " ",
							key = "x",
							desc = "Lazy Extras",
							action = ":LazyExtras",
						},
						{
							icon = "󰒲 ",
							key = "L",
							desc = "Lazy",
							action = ":Lazy",
							enabled = package.loaded.lazy ~= nil,
						},
						{ icon = " ", key = "q", desc = "Quit", action = ":qa" },
					},
				},
				sections = {
					{ section = "header" },
					{ section = "keys", gap = 1, padding = 1 },
					{ section = "startup" },
				},
			},
		},
		keys = {
			{
				"<leader>un",
				function()
					Snacks.notifier.hide()
				end,
				desc = "Dismiss All Notifications",
			},
			{
				"<leader>bd",
				function()
					Snacks.bufdelete()
				end,
				desc = "Delete Buffer",
			},
			{
				"<leader>zt",
				function()
					Snacks.lazygit()
				end,
				desc = "Lazygit",
			},
			{
				"<leader>gb",
				function()
					Snacks.git.blame_line()
				end,
				desc = "Git Blame Line",
			},
			-- { "<leader>gB", function() Snacks.gitbrowse() end, desc = "Git Browse" },
			{
				"<leader>zh",
				function()
					Snacks.lazygit.log_file()
				end,
				desc = "Lazygit Current File History",
			},
			{
				"<leader>zl",
				function()
					Snacks.lazygit.log()
				end,
				desc = "Lazygit Log (cwd)",
			},
			{
				"<leader>cR",
				function()
					Snacks.rename()
				end,
				desc = "Rename File",
			},
			-- { "<c-/>", function() Snacks.terminal() end, desc = "Toggle Terminal" },
			-- { "<c-_>", function() Snacks.terminal() end, desc = "which_key_ignore" },
			-- { "]]", function() Snacks.words.jump(vim.v.count1) end, desc = "Next Reference", mode = { "n", "t" } },
			-- { "[[", function() Snacks.words.jump(-vim.v.count1) end, desc = "Prev Reference", mode = { "n", "t" } },
			{
				"<leader><leader>N",
				desc = "Neovim News",
				function()
					Snacks.win({
						file = vim.api.nvim_get_runtime_file("doc/news.txt", false)[1],
						width = 0.6,
						height = 0.6,
						wo = {
							spell = false,
							wrap = false,
							signcolumn = "yes",
							statuscolumn = " ",
							conceallevel = 3,
						},
					})
				end,
			},
		},
		init = function()
			vim.api.nvim_create_autocmd("User", {
				pattern = "VeryLazy",
				callback = function()
					-- Setup some globals for debugging (lazy-loaded)
					_G.dd = function(...)
						Snacks.debug.inspect(...)
					end
					_G.bt = function()
						Snacks.debug.backtrace()
					end
					vim.print = _G.dd -- Override print to use snacks for `:=` command

					-- Create some toggle mappings
					Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
					Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
					Snacks.toggle.option("number", { name = "Relative Number" }):map("<leader>ul")
					Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("<leader>uL")
					Snacks.toggle.diagnostics():map("<leader>ud")
					Snacks.toggle
						.option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 })
						:map("<leader>uc")
					Snacks.toggle.treesitter():map("<leader>uT")
					Snacks.toggle
						.option("background", { off = "light", on = "dark", name = "Dark Background" })
						:map("<leader>ub")
					Snacks.toggle.inlay_hints():map("<leader>uh")
				end,
			})
		end,
	},

	{
		"chentoast/marks.nvim",
		event = "VeryLazy",
		opts = {

			mappings = {
				toggle = "mm",
				next = "[m",
				prev = "]m", -- pass false to disable only this default mapping
				delete_buf = "-m", -- pass false to disable only this default mapping
				delete_line = "=m", -- pass false to disable only this default mapping
			},
		},
	},

	{
		"williamboman/mason.nvim",
		keys = nil,
		opts = {
			-- install_root_dir = vim.g.sd_vim_dir .. "/mason",
			ensure_installed = {
				-- !!@ lsp
				"ansible-language-server",
				"bash-language-server",
				"css-lsp",
				"docker-compose-language-service",
				"dockerfile-language-server",
				"gofumpt",
				"goimports",
				"gopls",
				"hclfmt",
				"html-lsp",
				"json-lsp",
				"lua-language-server",
				"pyright",
				"quick-lint-js",
				"shellcheck",
				"stylua",
				"templ",
				"terraform-ls",
				-- "trivy",
				"vim-language-server",
				"vue-language-server",
				"yaml-language-server",
				-- "grammarly-languageserver",
				-- "templ",
				-- !!@ formatter/linter
				"prettier",
				"selene",
				"staticcheck",
				-- "cspell",
				-- "prettierd",
				-- "shellcheck",
				-- "shfmt",
				-- "stylua",
				-- "textlint",
				-- "yamlfmt",
			},
		},
	},

	{
		"uga-rosa/cmp-dictionary",
		opts = {
			paths = { vim.g.sd_vim_dir .. "/words" },
			exact_length = 2,
			first_case_insensitive = true,
			document = {
				enable = false,
				command = { "wn", "${label}", "-over" },
			},
		},
	},

	{
		"hrsh7th/nvim-cmp",
		lazy = true,
		event = "InsertEnter",
		dependencies = {
			"hrsh7th/cmp-nvim-lsp",
			-- "hrsh7th/cmp-buffer",
			-- "hrsh7th/cmp-path",
			-- {
			--  "garymjr/nvim-snippets",
			--  opts = {
			--    friendly_snippets = true,
			--  },
			--  dependencies = { "rafamadriz/friendly-snippets" },
			-- },
			"uga-rosa/cmp-dictionary",
		},
		opts = {
			completion = {
				completeopt = "menu,menuone,noinsert,noselect",
			},
			preselect = require("cmp").PreselectMode.None,
			-- snippet = {
			--  expand = function(item)
			--    return LazyVim.cmp.expand(item.body)
			--  end,
			-- },
			mapping = require("cmp").mapping.preset.insert({
				["<Down>"] = require("cmp").mapping.select_next_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				["<Up>"] = require("cmp").mapping.select_prev_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				["<C-n>"] = require("cmp").mapping.select_next_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				["<C-p>"] = require("cmp").mapping.select_prev_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				["<tab>"] = require("cmp").mapping.select_next_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				["<S-tab>"] = require("cmp").mapping.select_prev_item({
					behavior = require("cmp").SelectBehavior.Insert,
				}),
				-- ["<C-Space>"] = require("cmp").mapping.complete(),
				["<C-e>"] = require("cmp").mapping.abort(),
				["<C-c>"] = require("cmp").mapping.abort(),
				["<CR>"] = require("cmp").mapping.confirm({ select = false }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
				-- ctrl+;
				["<INSERT>"] = require("cmp").mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
				-- Accept multi-line completion
				["<C-y>"] = require("cmp").mapping.confirm({
					behavior = require("cmp").ConfirmBehavior.Insert,
					select = false,
				}),
			}),
			sources = require("cmp").config.sources({
				-- { name = "fittencode", group_index = 1 },
				{ name = "path" },
				{ name = "codeium" },
				{ name = "snippets" },
				{ name = "nvim_lsp" },
				{
					name = "buffer",
					option = {
						get_bufnrs = function()
							local bufs = {}
							for _, win in ipairs(vim.api.nvim_list_wins()) do
								bufs[vim.api.nvim_win_get_buf(win)] = true
							end
							return vim.tbl_keys(bufs)
						end,
					},
				},
				{
					name = "dictionary",
					keyword_length = 2,
				},
			}),
			experimental = {
				ghost_text = false,
			},
		},
	},

	{
		"neovim/nvim-lspconfig",
		keys = {
			{
				"<leader>cl",
				function()
					vim.fn.Sd_compress_dup_lines()
				end,
				mode = { "n" },
			},
			{
				"QEE",
				function()
					local bufnr = vim.api.nvim_get_current_buf()
					local active_clients = vim.lsp.get_clients({ bufnr = bufnr })
					if next(active_clients) == nil then
						vim.cmd("LspStart")
						print("Lsp start!")
					else
						vim.cmd("LspRestart")
						print("Lsp restart!")
					end
				end,
				mode = { "n" },
			},
			{
				"QDD",
				function()
					local bufnr = vim.api.nvim_get_current_buf()
					local active_clients = vim.lsp.get_clients({ bufnr = bufnr })
					if next(active_clients) == nil then
						print("No LSP to stop")
					else
						vim.cmd("LspStop")
						print("Lsp Stopped!")
					end
				end,
				mode = { "n" },
			},
			{ "QII", "<cmd>LspInfo<CR>", mode = { "n" } },
		},
		opts = {
			diagnostics = {
				underline = true,
				update_in_insert = false,
				virtual_text = false,
				-- float = {
				--  show_header = false,
				--  header = "",
				--  source = true,
				--  focus = false,
				--  width = 80,
				-- },
				severity_sort = true,
				text = {
					[vim.diagnostic.severity.ERROR] = LazyVim.config.icons.diagnostics.Error,
					[vim.diagnostic.severity.WARN] = LazyVim.config.icons.diagnostics.Warn,
					[vim.diagnostic.severity.HINT] = LazyVim.config.icons.diagnostics.Hint,
					[vim.diagnostic.severity.INFO] = LazyVim.config.icons.diagnostics.Info,
				},
			},
			inlay_hints = {
				enabled = false,
			},
			document_highlight = {
				enabled = false,
			},
			servers = {
				ansiblels = {
					settings = {
						ansible = {
							ansible = {
								path = "ansible",
							},
							executionEnvironment = {
								enabled = false,
							},
							python = {
								interpreterPath = "python",
							},
							validation = {
								enabled = true,
								lint = {
									enabled = false,
									path = "ansible-lint",
								},
							},
						},
					},
				},
			},
		},
	},

	{
		"stevearc/conform.nvim",
		keys = {
			{
				"--",
				function()
					if vim.o.ft == "python" then
						require("conform").format({
							async = false,
							lsp_fallback = true,
							timeout_ms = 3000,
							quiet = false,
						}, function(err)
							if not err then
								vim.api.nvim_command("write")
								print("Format Done!")
							else
								print("Format Error!")
							end
						end)
					else
						vim.api.nvim_command("LazyFormat")
						vim.api.nvim_command("write")
						print("Format Done!")
					end
				end,
				mode = { "n", "v" },
			},
			{
				"==",
				function()
					if vim.o.ft == "python" then
						require("conform").format({
							async = false,
							lsp_fallback = true,
							timeout_ms = 4000,
							quiet = false,
							formatters = { "sd_ruff" },
						}, function(err)
							if not err then
								vim.api.nvim_command("write")
								print("Format Done!")
							else
								print("Format Error!")
							end
						end)
					else
						vim.api.nvim_command("LazyFormat")
						vim.api.nvim_command("write")
						print("Format Done!")
					end
				end,
				mode = { "n", "v" },
			},
		},
		opts = {
			formatters_by_ft = {
				python = function()
					if vim.fn.executable("yapf") == 1 then
						return { "yapf", "isort" }
					elseif vim.fn.executable("usort") == 1 then
						return { "black", "usort" }
					elseif vim.fn.executable("isort") == 1 then
						return { "black", "isort" }
					else
						return { "black" }
					end
				end,
				-- go = { "gofmt" },
				go = { "goimports", "gofumpt" },
				css = { "prettier" },
				html = { "prettier" },
				htmldjango = { "prettier" },
				javascript = { "prettier" },
				javascriptreact = { "prettier" },
				json = { "prettier" },
				less = { "prettier" },
				lua = { "stylua" },
				sh = { "shfmt" },
				scss = { "prettier" },
				typescript = { "prettier" },
				typescriptreact = { "prettier" },
				vue = { "prettier" },
				yaml = { "prettier" },
			},
			formatters = {
				shfmt = {
					prepend_args = { "-i", "2", "-ci", "-bn" },
					-- args = { "-i", "2", "-ci", "-bn" },
				},
				black = {
					prepend_args = { "--line-length=88", "--preview" },
				},
				sd_ruff = {
					command = "ruff",
					args = {
						"format",
						"--preview",
						"--line-length",
						"120",
						"--target-version",
						"py311",
						"--stdin-filename",
						"$FILENAME",
						"-",
					},
					inherit = true,
					-- prepend_args = { "--preview", "--line-length", "88", "--target-version", "py311" },
					-- args = { '--fix', '--preview', '--line-length', '88', '--target-version', 'py311', '-', '--stdin-filename' },
				},
				ruff_fix = {
					prepend_args = { "--preview", "--line-length", "120", "--target-version", "py311" },
				},
			},
		},
	},

	{
		"nvim-lualine/lualine.nvim",
		opts = {
			extensions = {
				"man",
				"quickfix",
				"neo-tree",
				"toggleterm",
				"lazy",
			},
			options = {
				theme = bubbles_theme,
				-- component_separators = '',
				section_separators = { left = "", right = "" },
				-- theme = "onedark",
				-- theme = "nightfly",
				-- theme = "material",
				-- theme = "dracula",
				-- theme = "auto",
				-- theme = "codedark",
				globalstatus = true,
				disabled_filetypes = { statusline = { "dashboard", "alpha", "starter" } },
				refresh = { statusline = 500 },
				component_separators = "",
				-- component_separators = { left = '', right = '' },
				-- section_separators = { left = '', right = '' },
				icons_enabled = false,
				always_show_tabline = true,
			},
			-- sections = lualine_process_sections {
			sections = {

				lualine_a = {
					{
						function()
							return " "
						end,
						cond = function()
							if os.getenv("TMUX") then
								return true
							end
							return false
						end,
						separator = {},
						left_padding = 0,
						right_padding = 0,
						color = { bg = "#00f6b8", gui = "none" },
						-- color = { bg = "#BD93F9", gui = "none" },
					},
					{
						function()
							local file = io.open("/tmp/tmux_info", "r")
							if file == nil then
								return
							end
							local contents = file:read("l")
							file:close()
							if contents == nil then
								return "nil_"
							else
								return contents
							end
						end,
						cond = function()
							if os.getenv("TMUX") then
								return true
							end
							return false
						end,
						left_padding = 0,
						right_padding = 0,
						-- color = { "#BD93F9", fg = "#BD93F9" },
						-- color = { bg = "#00f6b8", gui = "none" },
					},
					{
						function()
							local file = io.open("/tmp/tmux_info", "r")
							if file == nil then
								return
							end
							local _ = file:read("l")
							local contents = file:read("l")
							file:close()
							if contents == nil then
								return "nil_"
							else
								return contents
							end
						end,
						cond = function()
							if os.getenv("TMUX") then
								return true
							end
							return false
						end,
						separator = { right = "" },
						left_padding = 0,
						right_padding = 0,
						color = { bg = "#c099ff" },
						-- color = { bg = "#00f6b8", gui = "none" },
					},
					{
						"mode",
						separator = { right = "" },
						right_padding = 2,
						cond = function()
							if os.getenv("TMUX") then
								return false
							end
							return true
						end,
					},
				},
				lualine_b = {
					{
						"branch",
						color = { bg = "#303030", fg = "#77aafa" },
						separator = { right = "" },
						left_padding = 2,
						right_padding = 1,
					},
					{
						"diff",
						color = { bg = "#303030" },
						separator = { right = "" },
						right_padding = 1,
					},
				},
				lualine_c = {
					{
						"filename",
						file_status = true,
						symbols = {
							modified = "[+]", -- Text to show when the file is modified.
							readonly = "", -- Text to show when the file is non-modifiable or readonly.
							unnamed = "[No Name]", -- Text to show for unnamed buffers.
							newfile = "[New]", -- Text to show for newly created file before first write
						},
						path = 3,
						-- 0: Just the filename
						-- 1: Relative path
						-- 2: Absolute path
						-- 3: Absolute path, with tilde as the home directory
						-- 4: Filename and parent dir, with tilde as the home directory
						-- color = { fg = "#BD93F9", gui = "none", bg = "#282828" },
						color = { bg = "#1e1e1e", fg = "#b7b7b7" },
						-- color = { bg = "#2c2c3c", fg = "#b7b7b7" },
						separator = { right = "" },
						right_padding = 1,
					},
					{
						function()
							if
								vim.fn.exists("*tablemode#IsActive") == 1
								and vim.api.nvim_call_function("tablemode#IsActive", {}) == 1
							then
								return "[TableMode]"
							end
							return ""
						end,
						color = { fg = "#000000", bg = "#BD93F9", gui = "none" },
					},
					{
						function()
							if vim.b.venn_enable == 1 then
								return "[DrawingMode]"
							end
							return ""
						end,
						color = { fg = "#000000", bg = "#82AAFF", gui = "none" },
					},
					{
						require("noice").api.status.search.get,
						cond = require("noice").api.status.search.has,
						color = { fg = "#ff9e64" },
					},
				},

				lualine_x = {
					"diagnostics",
					{
						function()
							local bufnr = vim.api.nvim_get_current_buf()
							local active_clients = vim.lsp.get_clients({ bufnr = bufnr })
							if next(active_clients) == nil then
								return " " -- Beautiful icon indicating no active LSP client
							else
								local names = {}
								for _, client in ipairs(active_clients) do
									table.insert(names, client.name)
								end
								local icon = " " -- Custom icon for active LSP clients
								return icon .. " " .. table.concat(names, ", ") -- Return a nice icon before the list of LSP names
							end
						end,
						color = { bg = "#1e1e1e", fg = "#b7b7b7" },
						separator = { left = "" },
						left_padding = 2,
					},
          -- stylua: ignore
          {
            function() return require("noice").api.status.command.get() end,
            cond = function() return package.loaded["noice"] and require("noice").api.status.command.has() end,
            color = function() return LazyVim.ui.fg("Statement") end,
          },
          -- stylua: ignore
          {
            function() return require("noice").api.status.mode.get() end,
            cond = function() return package.loaded["noice"] and require("noice").api.status.mode.has() end,
            color = function() return LazyVim.ui.fg("Constant") end,
          },
          -- stylua: ignore
          {
            require("lazy.status").updates,
            cond = require("lazy.status").has_updates,
            color = function() return LazyVim.ui.fg("Special") end,
          },
				},

				lualine_y = {
					{
						"%l:%c / %p%% %L",
						-- color = { bg = "#504945", fg = "#9f917e" },
						color = { bg = "#303030", fg = "#b7b7b7" },
					},
					{
						"filetype",
						colored = false, -- Displays filetype icon in color if set to true
						-- icon_only = false,          -- Display only an icon for filetype
						-- icon = { align = 'right' }, -- Display filetype icon on the right hand side
						color = { bg = "#303030", fg = "#b7b7b7" },
					},
				},

				lualine_z = {
					{
						"hostname",
						left_padding = 0,
						right_padding = 0,
					},
				},
			},
		},
	},

	{
		"nvim-telescope/telescope.nvim",
		dependencies = {
			"nvim-telescope/telescope-symbols.nvim",
		},
		cmd = "Telescope",
		version = false,
		opts = {
			defaults = {
				prompt_prefix = " ",
				selection_caret = " ",
				path_display = { "tail" },
				layout_config = {
					horizontal = {
						preview_cutoff = 0,
						prompt_position = "bottom",
					},
				},
				preview = {
					hide_on_startup = false,
				},
				dynamic_preview_title = true,
				mappings = {
					i = {
						["<C-u>"] = false,
						["<C-Down>"] = function(...)
							return require("telescope.actions").cycle_history_next(...)
						end,
						["<C-Up>"] = function(...)
							return require("telescope.actions").cycle_history_prev(...)
						end,
						["<C-f>"] = function(...)
							return require("telescope.actions").preview_scrolling_down(...)
						end,
						["<C-b>"] = function(...)
							return require("telescope.actions").preview_scrolling_up(...)
						end,
					},
					n = {
						["q"] = function(...)
							return require("telescope.actions").close(...)
						end,
						["\\"] = function(...)
							return require("telescope.actions").file_vsplit(...)
						end,
					},
				},
			},
			pickers = {
				git_status = { preview = { hide_on_startup = false } },
				live_grep = { preview = { hide_on_startup = false } },
			},
			extensions = {},
		},
		keys = function()
			return {
				{
					"<leader>fw",
					function()
						require("telescope.builtin").live_grep({
							additional_args = function(args)
								return vim.list_extend(args, { "--hidden", "--no-ignore" })
							end,
						})
					end,
					desc = "Find words in all files",
				},
				{
					"<leader>fs",
					"<cmd>Telescope symbols<CR>",
					desc = "Doc symbols",
				},
			}
		end,
		config = function(_, opts)
			local previewers = require("telescope.previewers")
			local new_maker = function(filepath, bufnr, opts)
				opts = opts or {}
				filepath = vim.fn.expand(filepath)
				vim.loop.fs_stat(filepath, function(_, stat)
					if not stat then
						return
					end
					if stat.size > 20000 then
						return
					else
						previewers.buffer_previewer_maker(filepath, bufnr, opts)
					end
				end)
			end
			opts.defaults.buffer_previewer_maker = new_maker
			require("telescope").setup(opts)
		end,
	},

	{
		"ibhagwan/fzf-lua",
		-- dependencies = { "nvim-tree/nvim-web-devicons" },
		keys = function()
			return {
				{
					"<leader>fn",
					"<cmd>NoiceFzf<cr>",
					desc = "Find notifications",
				},
				{
					"<leader>fh",
					"<cmd>FzfLua oldfiles<cr>",
					desc = "Recent",
					-- function()
					--   require("fzf-lua").oldfiles()
					-- end,
					-- mode = { "n" },
				},
				{
					"<space>q",
					"<cmd>FzfLua diagnostics_workspace<cr>",
					desc = "Document Diagnostics",
				},
				{
					"<leader>fd",
					"<cmd>FzfLua diagnostics_document<cr>",
					desc = "Document Diagnostics",
				},
				{
					"<leader>fD",
					"<cmd>FzfLua diagnostics_workspace<cr>",
					desc = "Workspace Diagnostics",
				},
				-- {
				--  "<leader>fd",
				--  function()
				--    require("fzf-lua").diagnostics_document()
				--  end,
				--  mode = { "n" },
				-- },
				-- {
				--  "<leader>FD",
				--  function()
				--    require("fzf-lua").diagnostics_workspace()
				--  end,
				--  mode = { "n" },
				-- },
				{
					"<leader>FF",
					function()
						local search_root = vim.fn.input("Enter file search root: ", LazyVim.root())
						if string.match(search_root, "^/") then
							require("fzf-lua").files({
								cwd = search_root,
								-- fd_opts = "--color=never --type f --hidden --follow --no-ignore",
							})
						end
					end,
					mode = { "n" },
				},
				{
					"<leader>ff",
					-- LazyVim.pick("auto"),
					-- desc = "Find Files (Root Dir)",
					function()
						require("fzf-lua").files({
							cwd = LazyVim.root(),
						})
					end,
				},
				{
					"<leader>FG",
					function()
						local search_root = vim.fn.input("Enter grep search root: ", LazyVim.root())
						if string.match(search_root, "^/") then
							require("fzf-lua").live_grep({
								cwd = search_root,
								-- rg_opts = "--color=never --hidden --follow --no-ignore",
							})
						end
					end,
					mode = { "n" },
				},
				{
					"<leader>fg",
					LazyVim.pick("live_grep"),
					desc = "Grep (Root Dir)",
					-- function()
					--  require("fzf-lua").live_grep({
					--    cwd = LazyVim.root(),
					--    -- rg_opts = "--color=never --hidden --follow --no-ignore",
					--  })
					-- end,
					-- mode = { "n" },
				},
				{
					"<leader>gg",
					LazyVim.pick("live_grep"),
					desc = "Grep (Root Dir)",
					-- function()
					--  require("fzf-lua").live_grep({
					--    cwd = LazyVim.root(),
					--    -- rg_opts = "--color=never --hidden --follow --no-ignore",
					--  })
					-- end,
					-- mode = { "n" },
				},
				{
					"<leader>gr",
					function()
						require("fzf-lua").resume()
					end,
					mode = { "n" },
				},
				{
					"<leader>fc", -- normal
					LazyVim.pick("grep_cword"),
					desc = "Word (Root Dir)",
					-- function()
					--  require("fzf-lua").grep_cword({
					--    cwd = LazyVim.root(),
					--    -- rg_opts = "--color=never --hidden --no-ignore",
					--  })
					-- end,
					-- mode = { "n" },
				},
				{
					"<leader>fc", -- visual
					LazyVim.pick("grep_visual"),
					mode = "v",
					desc = "Selection (Root Dir)",
					-- function()
					--  require("fzf-lua").grep_visual({
					--    cwd = LazyVim.root(),
					--    -- rg_opts = "--color=never --hidden --no-ignore",
					--  })
					-- end,
					-- mode = { "v" },
				},
				{
					"<leader>fr",
					function()
						require("fzf-lua").lsp_references()
					end,
					mode = { "n" },
				},
				{
					"QO",
					function()
						require("fzf-lua").lsp_document_symbols()
					end,
					mode = { "n" },
				},
				{
					"<leader>fo",
					function()
						require("fzf-lua").lsp_document_symbols()
					end,
					mode = { "n" },
				},
				{
					"<leader>FO",
					function()
						require("fzf-lua").lsp_workspace_symbols()
					end,
					mode = { "n" },
				},
				{
					"<leader>fk",
					function()
						require("fzf-lua").keymaps()
					end,
					mode = { "n" },
				},
				{
					"<leader>f/",
					"<cmd>FzfLua grep_curbuf<cr>",
					desc = "fuzzy search for current buffer",
				},
				-- {
				--  "<leader>fb",
				--  function()
				--    require("fzf-lua").changes()
				--  end,
				--  mode = { "n" },
				-- },
				-- {
				--  "<leader>u",
				--  "<cmd>FzfLua buffers sort_mru=true sort_lastused=true<cr>",
				--  desc = "Switch Buffer",
				--  mode = { "n" },
				-- },
			}
		end,
		config = function()
			local actions = require("fzf-lua.actions")

			require("fzf-lua").setup({
				-- fzf_bin         = 'sk',            -- use skim instead of fzf?
				-- https://github.com/lotabout/skim
				-- can also be set to 'fzf-tmux'
				keymap = {
					builtin = {
						["<c-f>"] = "preview-page-down",
						["<left>"] = "preview-page-up",
					},
					fzf = {
						["tab"] = "down",
						["shift-tab"] = "up",
						["ctrl-d"] = "half-page-down",
						["ctrl-u"] = "half-page-up",
					},
				},
				winopts = {
					width = 0.9,
					height = 0.8,
					row = 0.5,
					col = 0.5,
					preview = {
						scrollchars = { "┃", "" },
						-- default = "bat",
						horizontal = "right:40%",
						layout = "horizontal",
						-- layout = "vertical",
					},
				},
				buffers = {
					actions = {
						["default"] = { actions.buf_vsplit },
						["ctrl-t"] = { actions.buf_tabedit },
					},
				},
				files = {
					-- find_opts = [[-type f -not -path '*/\.git/*' -printf '%P\n']],
					-- rg_opts = [[--color=never --files --follow -g "!.git"]],
					-- fd_opts = [[--color=never --type f --follow --exclude .git]],
					actions = {
						-- inherits from 'actions.files', here we can override
						-- or set bind to 'false' to disable a default action
						-- action to toggle `--no-ignore`, requires fd or rg installed
						["ctrl-x"] = { actions.toggle_ignore },
						["ctrl-a"] = { actions.toggle_hidden },
						-- uncomment to override `actions.file_edit_or_qf`
						["default"] = actions.file_vsplit,
						["ctrl-g"] = false,
						-- custom actions are available too
						--   ["ctrl-y"]    = function(selected) print(selected[1]) end,
					},
				},
				grep = {
					actions = {
						-- actions inherit from 'actions.files' and merge
						-- this action toggles between 'grep' and 'live_grep'
						-- uncomment to enable '.gitignore' toggle for grep
						-- ["ctrl-r"]   = { actions.toggle_ignore }
						["ctrl-g"] = false,
						["ctrl-s"] = { actions.grep_lgrep },
						["ctrl-x"] = { actions.toggle_ignore },
						["ctrl-a"] = { actions.toggle_hidden },
					},
				},
			})
		end,
	},

	{
		"linux-cultist/venv-selector.nvim",
		dependencies = { "nvim-telescope/telescope.nvim" },
		branch = "regexp",
		cmd = "VenvSelect",
		opts = {
			cwd = false,
			search_workspace = false,
			enable_default_searches = false,
			on_venv_activate_callback = { Switch_venv_hook },
			enable_cached_venvs = true, -- use cached venvs that are activated automatically when a python file is registered with the LSP.
			cached_venv_automatic_activation = false, -- if set to false, the VenvSelectCached command becomes available to manually activate them.
			activate_venv_in_terminal = true, -- activate the selected python interpreter in terminal windows opened from neovim
			set_environment_variables = true, -- sets VIRTUAL_ENV or CONDA_PREFIX environment variables
			notify_user_on_venv_activation = false, -- notifies user on activation of the virtual env
			search_timeout = 5, -- if a search takes longer than this many seconds, stop it and alert the user
			debug = false, -- enables you to run the VenvSelectLog command to view debug logs
			require_lsp_activation = true, -- require activation of an lsp before setting env variables

			settings = {
				search = {
					anaconda_base_01 = {
						command = "fd /python$ /opt/anaconda3/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
					anaconda_base_02 = {
						command = "fd /python$ ~/anaconda3/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
					anaconda_base_03 = {
						command = "fd /python$ /opt/conda/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
					anaconda_base_04 = {
						command = "fd /python$ ~/conda/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
					anaconda_base_05 = {
						command = "fd /python$ ~/.files_saved/anaconda3/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
					anaconda_base_06 = {
						command = "fd /python$ ~/.files_saved/conda/envs --full-path --color never -E /proc --type file --type symlink",
						type = "anaconda",
					},
				},
			},
			-- name = {
			--  -- "envs",
			--  -- "bin",
			--  -- "*-django",
			--  -- "*-fastapi",
			--  "venv-django-*",
			--  "venv-fastapi-*",
			--  "venv-django-01",
			--  "venv-django-02",
			--  "venv-django-03",
			--  "venv-django-04",
			--  "venv-django-05",
			--  "venv-fastapi-01",
			--  "venv-fastapi-02",
			--  "venv-fastapi-03",
			--  "venv-fastapi-04",
			--  "venv-fastapi-05",
			--  "venv-01",
			--  "venv-02",
			--  "venv-03",
			--  "venv-04",
			--  "venv-05",
			--  -- "env-01",
			--  -- "env-02",
			--  -- "env-03",
			--  -- "env-04",
			--  -- "env-05",
			--  -- ".venv",
			--  -- "env",
			--  -- ".env",
			-- },
		},
		init = function()
			-- function Switch_venv_hook(venv_path, venv_python)
			function Switch_venv_hook(_, _)
				vim.cmd("LspRestart")
				print("Lsp restart!")
			end
		end,
		keys = {
			{ "<leader>sc", "<cmd>VenvSelectCached<cr>" },
			{ "<leader>sv", "<cmd>VenvSelect<cr>" },
		},
	},

	{
		"folke/flash.nvim",
		keys = function()
			return {
				{
					"s",
					mode = { "n", "x", "o" },
					function()
						require("flash").jump()
					end,
					desc = "Flash",
				},
				{
					"S",
					mode = { "n", "o" },
					function()
						require("flash").treesitter()
					end,
					desc = "Flash Treesitter",
				},
				{
					"r",
					mode = { "o" },
					function()
						require("flash").remote()
					end,
					desc = "Remote Flash",
				},
				{
					"R",
					mode = { "o", "x" },
					function()
						require("flash").treesitter_search()
					end,
					desc = "Treesitter Search",
				},
				{
					"<c-c>",
					mode = { "c" },
					function()
						require("flash").toggle()
					end,
					desc = "Toggle Flash Search",
				},
			}
		end,
		opts = {
			labels = "asdfghjklqwertyuiopzxcvbnm",
			search = {
				multi_window = true,
				forward = true,
				wrap = true,
				mode = "exact",
				incremental = false,
				exclude = {
					"notify",
					"cmp_menu",
					"noice",
					"flash_prompt",
					function(win)
						return not vim.api.nvim_win_get_config(win).focusable
					end,
				},
				trigger = "",
				max_length = nil, ---@type number?
			},
			jump = {
				jumplist = true,
				pos = "start", ---@type "start" | "end" | "range"
				history = false,
				register = false,
				nohlsearch = false,
				autojump = false,
				inclusive = nil, ---@type boolean?
				offset = nil, ---@type number
			},
			label = {
				uppercase = true,
				exclude = "",
				current = true,
				after = false, ---@type boolean|number[]
				before = true, ---@type boolean|number[]
				style = "overlay", ---@type "eol" | "overlay" | "right_align" | "inline"
				reuse = "lowercase", ---@type "lowercase" | "all"
				distance = true,
				min_pattern_length = 0,
				rainbow = {
					enabled = false,
					shade = 9,
				},
				format = function(opts)
					return { { opts.match.label, opts.hl_group } }
				end,
			},
			highlight = {
				backdrop = true,
				matches = true,
				priority = 5000,
				groups = {
					match = "FlashMatch",
					current = "FlashCurrent",
					backdrop = "FlashBackdrop",
					label = "FlashLabel",
				},
			},
			action = nil,
			pattern = "",
			continue = false,
			config = nil,
			modes = {
				search = {
					enabled = false,
					highlight = { backdrop = false },
					jump = { history = true, register = true, nohlsearch = true },
					search = {},
				},
				char = {
					enabled = false,
					config = function(opts)
						opts.autohide = vim.fn.mode(true):find("no") and vim.v.operator == "y"
						opts.jump_labels = opts.jump_labels and vim.v.count == 0
					end,
					autohide = false,
					jump_labels = false,
					multi_line = true,
					label = { exclude = "hjkliardc" },
					keys = { "f", "F", "t", "T", ";", "," },
					char_actions = function(motion)
						return {
							[";"] = "next",
							[","] = "prev",
							[motion:lower()] = "next",
							[motion:upper()] = "prev",
						}
					end,
					search = { wrap = false },
					highlight = { backdrop = true },
					jump = { register = false },
				},
				treesitter = {
					labels = "abcdefghijklmnopqrstuvwxyz",
					jump = { pos = "range" },
					search = { incremental = false },
					label = { before = true, after = true, style = "inline" },
					highlight = {
						backdrop = false,
						matches = false,
					},
				},
				treesitter_search = {
					jump = { pos = "range" },
					search = { multi_window = true, wrap = true, incremental = false },
					remote_op = { restore = true },
					label = { before = true, after = true, style = "inline" },
				},
				remote = {
					remote_op = { restore = true, motion = true },
				},
			},
			prompt = {
				enabled = true,
				prefix = { { "", "FlashPromptIcon" } },
				win_config = {
					relative = "editor",
					width = 1,
					height = 1,
					row = -1,
					col = 0,
					zindex = 1000,
				},
			},
			remote_op = {
				restore = false,
				motion = false,
			},
		},
		init = function()
			local Config = require("flash.config")
			local Char = require("flash.plugins.char")
			for _, motion in ipairs({ "f", "t", "F", "T" }) do
				vim.keymap.set({ "n", "x", "o" }, motion, function()
					require("flash").jump(Config.get({
						mode = "char",
						search = {
							mode = Char.mode(motion),
							max_length = 1,
						},
					}, Char.motions[motion]))
				end)
			end
		end,
	},

	{
		"nvim-neo-tree/neo-tree.nvim",
		branch = "v3.x",
		cmd = "Neotree",
		keys = function()
			return {
				{
					"<leader>E",
					function()
						require("neo-tree.command").execute({
							-- dir = vim.loop.cwd(),
							dir = vim.uv.cwd(),
							toggle = true,
							reveal = true,
							reveal_force_cwd = true,
							position = "float",
						})
					end,
					desc = "Explorer NeoTree (cwd)",
				},
				{
					"<leader>e",
					function()
						require("neo-tree.command").execute({
							toggle = true,
							reveal = true,
							reveal_force_cwd = true,
							position = "float",
							dir = LazyVim.root(),
						})
					end,
					desc = "Explorer NeoTree (Root Dir)",
				},
			}
		end,
		opts = {
			-- sources = { "filesystem", "buffers", "git_status", "document_symbols" },
			sources = { "filesystem" },
			open_files_do_not_replace_types = { "terminal", "Trouble", "trouble", "qf", "Outline" },
			filesystem = {
				bind_to_cwd = true,
				follow_current_file = { enabled = true, leave_dirs_open = true },
				use_libuv_file_watcher = true,
				filtered_items = {
					visible = true,
					hide_dotfiles = false,
					hide_gitignored = false,
					hide_hidden = true,
					hide_by_name = {
						--"node_modules"
					},
					hide_by_pattern = {},
					always_show = {
						--".gitignored",
					},
					never_show = {
						--".DS_Store",
						--"thumbs.db"
					},
					never_show_by_pattern = {
						"LICENCE",
						"LICENSE",
						"meta",
						"*pytest_cache",
						".git",
						"__pycache__",
						"src/*/tsconfig.json",
						".null-ls_*",
					},
				},
				-- window = {
				--   mappings = {
				--     ["<bs>"] = "navigate_up",
				--     ["."] = "set_root",
				--     ["QH"] = "toggle_hidden",
				--     ["?"] = "fuzzy_finder",
				--     ["D"] = "fuzzy_finder_directory",
				--     ["#"] = "fuzzy_sorter",
				--     ["f"] = "filter_on_submit",
				--     ["<c-x>"] = "clear_filter",
				--     ["[g"] = "prev_git_modified",
				--     ["]g"] = "next_git_modified",
				--   },
				--   fuzzy_finder_mappings = {
				--     ["<down>"] = "move_cursor_down",
				--     ["<C-n>"] = "move_cursor_down",
				--     ["<up>"] = "move_cursor_up",
				--     ["<C-p>"] = "move_cursor_up",
				--   },
				-- },
			},
			default_component_configs = {
				indent = {
					with_expanders = true, -- if nil and file nesting is enabled, will enable expanders
					expander_collapsed = "",
					expander_expanded = "",
					expander_highlight = "NeoTreeExpander",
				},
			},
			window = {
				mappings = {
					["O"] = { "show_help", nowait = false, config = { title = "Order by", prefix_key = "o" } },
					["oc"] = { "order_by_created", nowait = false },
					["od"] = { "order_by_diagnostics", nowait = false },
					["om"] = { "order_by_modified", nowait = false },
					["on"] = { "order_by_name", nowait = false },
					["os"] = { "order_by_size", nowait = false },
					["ot"] = { "order_by_type", nowait = false },
					["u"] = "navigate_up",
					["<bs>"] = "navigate_up",
					["<2-LeftMouse>"] = "open",
					["<cr>"] = "open",
					["<esc>"] = "close_window",
					["P"] = { "toggle_preview", config = { use_float = true } },
					["<space>"] = "none",
					["#"] = "none",
					["/"] = "none",
					["z"] = "none",
					["H"] = "none",
					["L"] = "none",
					["h"] = "none",
					["e"] = "none",
					["b"] = "none",
					["l"] = "none",
					["x"] = "none",
					["w"] = "none",
					["C"] = "none",
					["Z"] = "none",
					["S"] = "open_split",
					["s"] = "open_vsplit",
					["t"] = "open_tabnew",
					["a"] = { "add", config = { show_path = "none" } },
					["A"] = "add_directory",
					["d"] = "delete",
					["r"] = "rename",
					["y"] = "copy_to_clipboard",
					["p"] = "paste_from_clipboard",
					["c"] = "copy",
					["m"] = "move",
					["q"] = "close_window",
					["<c-c>"] = "close_window",
					["R"] = "refresh",
					["g?"] = "show_help",
					["<"] = "prev_source",
					[">"] = "next_source",
					["Y"] = {
						function(state)
							local node = state.tree:get_node()
							local path = node:get_id()
							vim.fn.setreg("+", path, "c")
						end,
						desc = "Copy Path to Clipboard",
					},
				},
			},
		},
		deactivate = function()
			vim.cmd([[Neotree close]])
		end,
	},

	{
		"kylechui/nvim-surround",
		event = "VeryLazy",
		keys = {
			{
				"<space>l",
				mode = { "n" },
				"<Plug>(nvim-surround-normal-cur)",
			},
			{
				"<space>",
				mode = { "n", "x", "o" },
				"<Plug>(nvim-surround-normal-line)",
			},
			{
				"<space>",
				mode = { "v" },
				"<Plug>(nvim-surround-visual-line)",
			},
		},
		config = function()
			require("nvim-surround").setup({})
		end,
	},

	{
		"echasnovski/mini.bufremove",
		keys = function()
			return {
				{
					"qq",
					function()
						vim.fn.Sd_close_anything(1)
					end,
				},
				{
					"QQ",
					function()
						vim.fn.Sd_close_anything(2)
					end,
				},
				{
					"<localleader>rr",
					function()
						vim.fn.Sd_reopen_files(1)
					end,
				},
				{
					"<localleader>r1",
					function()
						vim.fn.Sd_reopen_files(1)
					end,
				},
				{
					"<localleader>r2",
					function()
						vim.fn.Sd_reopen_files(2)
					end,
				},
				{
					"<localleader>r3",
					function()
						vim.fn.Sd_reopen_files(3)
					end,
				},
				{
					"<localleader>r4",
					function()
						vim.fn.Sd_reopen_files(4)
					end,
				},
				{
					"<localleader>r5",
					function()
						vim.fn.Sd_reopen_files(5)
					end,
				},
				{
					"<localleader>r6",
					function()
						vim.fn.Sd_reopen_files(6)
					end,
				},
				{
					"<localleader>l",
					function()
						vim.fn.Sd_GetCloseDFileList()
					end,
				},
			}
		end,
		init = function()
			vim.cmd([[
        let g:sd_closed_file_list = []

        function! Sd_close_anything(mode) abort
          if CurrentWindowIsEmptyVim()
            exe ':quit!'
          endif

          let g:sd_last_file_name = expand('%:p')

          " empty buffer [no name]
          if g:sd_last_file_name == "" || g:sd_last_file_name =~ '^term://' || g:sd_last_file_name =~ '.\+\/sd-[^\/]\+$' || IsBlank(g:sd_last_file_name) || g:sd_last_file_name =~ 'spectre$'
            " silent! lua require('mini.bufremove').wipeout(0, true)
            silent! exe ':bw!'
            return
          endif

          let item_index =  index(g:sd_closed_file_list, g:sd_last_file_name)
          if item_index >= 0 "item in list
            let g:trash = remove(g:sd_closed_file_list, item_index)
          endif
          let g:trash = add(g:sd_closed_file_list, g:sd_last_file_name)

          if a:mode == 1
            silent! lua require('mini.bufremove').delete(0, true)
          else
            silent! exe ':bd!'
          endif
        endfunction

        function! Sd_reopen_files(code)
          if len(g:sd_closed_file_list) == 0
            let g:sd_notify = "Empty! recently closed files : " . string(g:sd_closed_file_list)
            echo g:sd_notify
            return
          endif

          let reverseClosedFileList = reverse(copy(g:sd_closed_file_list))
          if a:code == 'r'
            let num = -1
          else
            let num = -( a:code + 0)
            if - num > len(g:sd_closed_file_list)
              let g:t = num
              let g:sd_notify = "input num great than the max length of ClosedFileList!\n\nrecently closed file\n"
              let fileIndex = 1
              for item in reverseClosedFileList
                let g:sd_notify = g:sd_notify ."\n" . fileIndex . ": " . item
                let fileIndex = fileIndex + 1
              endfor
              echo g:sd_notify
              return
            endif
          endif
          let fileChoosen = g:sd_closed_file_list[num]
          if CurrentWindowIsEmptyVim()
            silent! exe "edit " . fileChoosen
            " echo "reopen: " . fileChoosen
            let g:sd_notify = "reopen: " . fileChoosen
            echo g:sd_notify
          else
            silent! exe "vsplit " . fileChoosen
            " echo "reopen: " . fileChoosen
            let g:sd_notify = "reopen: " . fileChoosen
            echo g:sd_notify
          endif
          let indexOfReopenFile = len(g:sd_closed_file_list) + num
          let g:trash = remove(g:sd_closed_file_list, indexOfReopenFile)
          if len(g:sd_closed_file_list) > 0
            let g:sd_last_file_name = g:sd_closed_file_list[-1]
          endif
        endfunction

        function! Sd_GetCloseDFileList()
          let reverseClosedFileList = reverse(copy(g:sd_closed_file_list))
          let fileIndex = 1
          let g:sd_notify =  "recently closed file\n"
          for item in reverseClosedFileList
            let g:sd_notify = g:sd_notify ."\n" . fileIndex . ": " . item
            let fileIndex = fileIndex + 1
          endfor
          echo g:sd_notify
        endfunction

      ]])
		end,
	},

	{
		"JoosepAlviste/nvim-ts-context-commentstring",
		lazy = true,
		opts = {
			enable_autocmd = false,
		},
	},

	{
		"echasnovski/mini.comment",
		-- event = "VeryLazy",
		keys = function()
			return {
				{ "gc", mode = { "n", "x", "o" } },
			}
		end,
		dependencies = "JoosepAlviste/nvim-ts-context-commentstring",
		opts = {
			options = {
				ignore_blank_line = true,
				pad_comment_parts = true,
				start_of_line = false,
				custom_commentstring = function()
					-- if vim.api.nvim_buf_get_option(0, "filetype") == "js" then
					--  return "-- %s"
					-- end
					return require("ts_context_commentstring.internal").calculate_commentstring()
						or vim.bo.commentstring
				end,
			},
		},
	},

	{
		"mbbill/undotree",
		cmd = "UndotreeToggle",
		keys = {
			{ "<leader>dd", mode = { "n" }, "<cmd>UndotreeToggle<cr>" },
		},
		init = function()
			vim.cmd([[
        let g:undotree_WindowLayout = 4
        let g:undotree_DiffpanelHeight = 20
        let g:undotree_SetFocusWhenToggle = 1
        let g:undotree_ShortIndicators = 1
        let g:undotree_SplitWidth = 45
        let g:undotree_HighlightChangedText = 1
        let g:undotree_HighlightSyntaxAdd  = "StrongMark"
        let g:undotree_HighlightSyntaxDel  = "StrongMark"
        let g:undotree_HighlightSyntaxChange  = "StrongMark"
        let g:undotree_HelpLine  = 0
        hi! def link diffRemoved Special
      ]])
		end,
	},

	{
		"windwp/nvim-autopairs",
		event = "InsertEnter",
		opts = {
			disable_filetype = { "TelescopePrompt", "spectre_panel" },
			disable_in_macro = false, -- disable when recording or executing a macro
			disable_in_visualblock = false, -- disable when insert after visual block mode
			disable_in_replace_mode = true,
			ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=],
			enable_moveright = true,
			enable_afterquote = true, -- add bracket pairs after quote
			enable_check_bracket_line = true, -- - check bracket in same line
			enable_bracket_in_quote = true, --
			enable_abbr = false, -- trigger abbreviation
			break_undo = true, -- switch for basic rule break undo sequence
			check_ts = false,
			map_cr = true,
			map_bs = true, -- map the <BS> key
			map_c_h = false, -- Map the <C-h> key to delete a pair
			map_c_w = false, -- map <c-w> to delete a pair if possible
			fast_wrap = {},
		},
	},

	{
		"echasnovski/mini.operators",
		-- Evaluate text and replace with output.
		-- Exchange text regions.
		-- Multiply (duplicate) text.
		-- Replace text with register.
		-- Sort text.
		event = "VeryLazy",
		-- !!@ cc not working propoer
		-- keys = {
		--     {"cv", mode = { "n", "x", "o"}},
		--     {"cm", mode = { "n", "x", "o"}},
		--     {"cs", mode = { "n", "x", "o"}},
		--     {"cx", mode = { "n", "x", "o"}},
		--     {"c=", mode = { "n", "x", "o"}},
		-- },
		version = false,
		config = function()
			-- local sort_func = function(content)
			--   local l_opts = {}
			--   if content.submode == 'v' then
			--     -- Ask for delimiter to be treated as is (not as Lua pattern)
			--     local delimiter = vim.fn.input('Sort delimiter: ')
			--     -- Treat surrounding whitespace as part of split
			--     l_opts.split_patterns = { '%s*' .. vim.pesc(delimiter) .. '%s*' }
			--   end
			--   return MiniOperators.default_sort_func(content, l_opts)
			-- end
			local operators = require("mini.operators")
			operators.setup({
				evaluate = {
					prefix = "c=",
					func = nil,
				},
				exchange = {
					prefix = "cx",
					reindent_linewise = true,
				},
				multiply = {
					prefix = "cm",
					func = nil,
				},
				replace = {
					prefix = "cv",
					reindent_linewise = true,
				},
				sort = {
					prefix = "<leader>so",
					func = nil,
				},
			})
			vim.cmd([[
          nnoremap <silent> cvl :normal cv$<CR>
          nnoremap <silent> cvv :normal Vcv<CR>
          nnoremap <silent> cxl :normal cx$<CR>
          nnoremap <silent> cxx :normal Vcx<CR>
          nnoremap <silent> <leader><leader>so :sort<CR>
      ]])
			-- !!@ cc not working propoer
			-- vim.keymap.set({ 'n', 'x',  'o' }, 'cvl', 'cv$', {remap = true})
			-- vim.keymap.set({ 'n', 'x',  'o' }, 'cxl', 'cx$', {remap = true})
		end,
	},

	{
		"junegunn/vim-easy-align",
		cmd = { "EasyAlign" },
		keys = {
			{
				"ga",
				mode = { "n", "x", "o" },
				"<Plug>(EasyAlign)",
			},
		},
		init = function()
			vim.cmd([[
        let g:easy_align_delimiters = {
              \ '>': {
              \      'pattern':     '>>\|=>\|>',
              \      },
              \ '/': {
              \     'pattern':         '//\+\|/\*\|\*/',
              \     'delimiter_align': 'l',
              \     'ignore_groups':   ['!Comment']
              \      },
              \ ')': {
              \     'pattern':       '[()]',
              \     'left_margin':   0,
              \     'right_margin':  0,
              \     'stick_to_left': 0
              \      },
              \ 'd': {
              \     'pattern':      ' \(\S\+\s*[;=]\)\@=',
              \     'left_margin':  0,
              \     'right_margin': 0
              \      },
              \ ':': {
              \     'pattern':      ':',
              \     'delimiter_align': 'r'
              \     },
              \ }
      ]])
		end,
	},

	{
		"nishigori/increment-activator",
		keys = { "<C-a>", "<C-x>" },
		init = function()
			vim.cmd([[
        let g:increment_activator_filetype_candidates =
            \ {
            \   '_': [
            \     ['get', 'post'],
            \     ['http', 'https'],
            \     ['no', 'yes'],
            \     ['No', 'Yes'],
            \     ['and', 'or'],
            \     ['false', 'true'],
            \     ['False', 'True'],
            \     ['info', 'warning', 'debug', 'error'],
            \     ['Info', 'Warning', 'Debug', 'Error'],
            \     ['ascending', 'descending'],
            \     ['Enable', 'Disable'],
            \     ['head', 'tail'],
            \     ['enable', 'disable'],
            \     ['enabled', 'disabled'],
            \     ['ascend', 'descend'],
            \     ['close', 'open'],
            \     ['abundant', 'scarce'],
            \     ['accept', 'decline'],
            \     ['accurate', 'inaccurate'],
            \     ['admit', 'deny'],
            \     ['advantage', 'disadvantage'],
            \     ['agree', 'disagree'],
            \     ['all', 'nothing'],
            \     ['ally', 'enemy'],
            \     ['answer', 'question'],
            \     ['approve', 'disapprove'],
            \     ['artificial', 'natural'],
            \     ['awake', 'asleep'],
            \     ['backward', 'forward'],
            \     ['before', 'after'],
            \     ['begin', 'end'],
            \     ['below', 'above'],
            \     ['bent', 'straight'],
            \     ['big', 'little'],
            \     ['bitter', 'sweet'],
            \     ['black', 'white'],
            \     ['bless', 'curse'],
            \     ['bold', 'meek'],
            \     ['brave', 'cowardly'],
            \     ['bright', 'dim'],
            \     ['capable', 'incapable'],
            \     ['careful', 'careless'],
            \     ['cheap', 'expensive'],
            \     ['clever', 'stupid'],
            \     ['clockwise', 'counterclockwise'],
            \     ['conceal', 'reveal'],
            \     ['contract', 'expand'],
            \     ['cool', 'warm'],
            \     ['correct', 'wrong'],
            \     ['create', 'destroy'],
            \     ['dangerous', 'safe'],
            \     ['daytime', 'nighttime'],
            \     ['dead', 'alive'],
            \     ['decrease', 'increase'],
            \     ['deep', 'shallow'],
            \     ['despair', 'hope'],
            \     ['discourage', 'encourage'],
            \     ['down', 'up'],
            \     ['downward', 'upward'],
            \     ['forward', 'backward'],
            \     ['dry', 'wet'],
            \     ['dusk', 'dawn'],
            \     ['early', 'late'],
            \     ['east', 'west', 'north', 'south'],
            \     ['easy', 'difficult'],
            \     ['empty', 'full'],
            \     ['enter', 'exit'],
            \     ['even', 'odd'],
            \     ['export', 'import'],
            \     ['exterior', 'interior'],
            \     ['external', 'internal'],
            \     ['fade', 'brighten'],
            \     ['fail', 'succeed'],
            \     ['famous', 'unknown'],
            \     ['few', 'many'],
            \     ['float', 'sink'],
            \     ['fold', 'unfold'],
            \     ['foolish', 'wise'],
            \     ['for', 'against'],
            \     ['forget', 'remember'],
            \     ['fortunate', 'unfortunate'],
            \     ['found', 'lost'],
            \     ['free', 'bound'],
            \     ['frequent', 'seldom'],
            \     ['fresh', 'stale'],
            \     ['generous', 'stingy'],
            \     ['gentle', 'rough'],
            \     ['giant', 'tiny'],
            \     ['girl', 'boy'],
            \     ['glad', 'sorry'],
            \     ['gloomy', 'cheerful'],
            \     ['good', 'bad'],
            \     ['great', 'unimportant'],
            \     ['guest', 'host'],
            \     ['guilty', 'innocent'],
            \     ['hate', 'love'],
            \     ['healthy', 'sick'],
            \     ['heaven', 'hell'],
            \     ['heavy', 'light'],
            \     ['here', 'there'],
            \     ['hero', 'coward'],
            \     ['high', 'low'],
            \     ['hill', 'valley'],
            \     ['hinder', 'help'],
            \     ['honest', 'dishonest'],
            \     ['horizontal', 'vertical'],
            \     ['hot', 'cold'],
            \     ['humble', 'proud'],
            \     ['in', 'out'],
            \     ['include', 'exclude'],
            \     ['inferior', 'superior'],
            \     ['inhale', 'exhale'],
            \     ['inner', 'outer'],
            \     ['inside', 'outside'],
            \     ['intentional', 'accidental'],
            \     ['interesting', 'boring'],
            \     ['join', 'separate'],
            \     ['junior', 'senior'],
            \     ['just', 'unjust'],
            \     ['justice', 'injustice'],
            \     ['knowledge', 'ignorance'],
            \     ['landlord', 'tenant'],
            \     ['large', 'small'],
            \     ['last', 'first'],
            \     ['laugh', 'cry'],
            \     ['lawful', 'illegal'],
            \     ['lazy', 'industrious'],
            \     ['leader', 'follower'],
            \     ['lend', 'borrow'],
            \     ['lengthen', 'shorten'],
            \     ['lenient', 'strict'],
            \     ['less', 'more'],
            \     ['likely', 'unlikely'],
            \     ['limited', 'boundless'],
            \     ['long', 'short'],
            \     ['loose', 'tight'],
            \     ['loss', 'win'],
            \     ['loyal', 'disloyal'],
            \     ['mad', 'sane'],
            \     ['major', 'minor'],
            \     ['mature', 'immature'],
            \     ['maximum', 'minimum'],
            \     ['melt', 'freeze'],
            \     ['merry', 'sad'],
            \     ['messy', 'neat'],
            \     ['minority', 'majority'],
            \     ['miser', 'spendthrift'],
            \     ['misunderstand', 'understand'],
            \     ['near', 'far'],
            \     ['never', 'always'],
            \     ['new', 'old'],
            \     ['night', 'day'],
            \     ['noisy', 'quiet'],
            \     ['obedient', 'disobedient'],
            \     ['offer', 'refuse'],
            \     ['on', 'off'],
            \     ['optimist', 'pessimist'],
            \     ['over', 'under'],
            \     ['past', 'present'],
            \     ['patient', 'impatient'],
            \     ['permanent', 'temporary'],
            \     ['poetry', 'prose'],
            \     ['polite', 'rude'],
            \     ['possible', 'impossible'],
            \     ['poverty', 'wealth'],
            \     ['powerful', 'weak'],
            \     ['pretty', 'ugly'],
            \     ['private', 'public'],
            \     ['prudent', 'imprudent'],
            \     ['pure', 'contaminated'],
            \     ['push', 'pull'],
            \     ['qualified', 'unqualified'],
            \     ['raise', 'lower'],
            \     ['rapid', 'slow'],
            \     ['rare', 'common'],
            \     ['real', 'fake'],
            \     ['regular', 'irregular'],
            \     ['rich', 'poor'],
            \     ['right', 'left'],
            \     ['same', 'opposite'],
            \     ['satisfactory', 'unsatisfactory'],
            \     ['scatter', 'collect'],
            \     ['secure', 'insecure'],
            \     ['serious', 'trivial'],
            \     ['shrink', 'grow'],
            \     ['singular', 'plural'],
            \     ['slim', 'fat'],
            \     ['sober', 'drunk'],
            \     ['soft', 'hard'],
            \     ['some', 'none'],
            \     ['sorrow', 'joy'],
            \     ['sow', 'reap'],
            \     ['stop', 'start'],
            \     ['stopped', 'started'],
            \     ['straight', 'crooked'],
            \     ['success', 'failure'],
            \     ['sunny', 'cloudy'],
            \     ['synonym', 'antonym'],
            \     ['take', 'give'],
            \     ['tame', 'wild'],
            \     ['thick', 'thin'],
            \     ['together', 'apart'],
            \     ['top', 'bottom'],
            \     ['tough', 'tender'],
            \     ['transparent', 'opaque'],
            \     ['truth', 'lie'],
            \     ['upstairs', 'downstairs'],
            \     ['useful', 'useless'],
            \     ['vacant', 'occupied'],
            \     ['vanish', 'appear'],
            \     ['victory', 'defeat'],
            \     ['virtue', 'vice'],
            \     ['visible', 'invisible'],
            \     ['voluntary', 'compulsory'],
            \     ['war', 'peace'],
            \     ['wax', 'wane'],
            \     ['wide', 'narrow'],
            \     ['wisdom', 'folly'],
            \   ],
            \   'erlang': [
            \     ['module', 'export'],
            \     [
            \       'is_alive', 'is_atom', 'is_binary', 'is_bitstring',
            \       'is_boolean', 'is_float', 'is_function',
            \       'is_integer', 'is_list', 'is_number',
            \       'is_pid', 'is_port', 'is_process_alive',
            \       'is_record', 'is_reference', 'is_tuple',
            \     ],
            \   ],
            \   'go': [
            \     ['byte', 'complex64', 'complex128'],
            \     ['Info', 'Warn', 'Debug', 'Error'],
            \     ['int', 'int8', 'int16', 'int32', 'int64'],
            \     ['uint', 'uint8', 'uint16', 'uint32', 'uint64'],
            \     ['float32', 'float64'],
            \     ['interface', 'struct'],
            \   ],
            \ }
      ]])
		end,
	},

	{
		"dhruvasagar/vim-table-mode",
		cmd = { "TableModeToggle", "TableModeEnable", "Tableize", "TableModeRealign" },
		keys = {
			{ "<leader><leader>tm", "<Cmd>TableModeToggle<CR>" },
			{ "<leader><leader>T", "<Cmd>Tableize<CR>" },
		},
		init = function()
			vim.cmd([[
        let g:table_mode_corner='+'
        let g:table_mode_corner_corner='+'
        let g:table_mode_header_fillchar='='
        let g:table_mode_map_prefix = '<Leader><Leader>t'
      ]])
		end,
	},

	{
		"nvim-pack/nvim-spectre",
		keys = {
			{
				"<leader>sr",
				function()
					vim.fn.Sd_quick_yank()
					require("spectre").open()
				end,
				desc = "Replace in files (Spectre)",
			},
		},
	},

	{
		"echasnovski/mini.completion",
		ft = { "javascript", "typescript", "python", "go", "lua", "vim" },
	},

	-- { "echasnovski/mini.visits", event = "VeryLazy"},

	{
		"echasnovski/mini.ai",
		event = "VeryLazy",
		opts = function()
			local ai = require("mini.ai")
			return {
				n_lines = 500,
				custom_textobjects = {
					o = ai.gen_spec.treesitter({ -- code block
						a = { "@block.outer", "@conditional.outer", "@loop.outer" },
						i = { "@block.inner", "@conditional.inner", "@loop.inner" },
					}),
					f = ai.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }, {}),
					c = ai.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }, {}),
					-- t = { "<([%p%w]-)%f[^<%w][^<>]->.-</%1>", "^<.->().*()</[^/]->$" },
					-- t = false,
					t = { "<([%p%w]-)%f[^<%w][^<>]->.-</%1>", "^<.->().*()</[^/]->$" }, -- tags
					-- f = false,
					-- c = false,
					p = ai.gen_spec.argument(),
					e = LazyVim.mini.ai_buffer, -- buffer
					a = false,
				},
				mappings = {
					-- Main textobject prefixes
					around = "a",
					inside = "i",
					-- Next/last textobjects
					around_next = "an",
					inside_next = "in",
					around_last = "al",
					inside_last = "il",
					-- Move cursor to corresponding edge of `a` textobject
					goto_left = "g[",
					goto_right = "g]",
				},
			}
		end,
		keys = function()
			return {}
		end,
		config = function(_, opts)
			require("mini.ai").setup(opts)
			vim.keymap.set({ "n", "x", "o" }, "[q", "g[q", { remap = true })
			vim.keymap.set({ "n", "x", "o" }, "]q", "g]q", { remap = true })
			vim.keymap.set({ "n", "x", "o" }, "[b", "g[b", { remap = true })
			vim.keymap.set({ "n", "x", "o" }, "]b", "g]b", { remap = true })
			-- vim.keymap.set({ 'n', 'x',  'o' }, '%', 'g[b', {remap = true})
		end,
	},

	{
		"urxvtcd/vim-indent-object",
		-- https://github.com/urxvtcd/vim-indent-object/blob/master/doc/indent-object.txt
		-- event = 'VeryLazy',
		init = function()
			vim.cmd([[
        function! Sd_indent_move(mode) abort
          if a:mode == "top"
            normal v[ao
            silent! exe "norm! \<esc>"
          elseif a:mode == "bottom"
            normal v]a
            silent! exe "norm! \<esc>"
          elseif a:mode == "up"
            normal v[io
            silent! exe "norm! \<esc>"
          elseif a:mode == "down"
            normal v]i
            silent! exe "norm! \<esc>"
          else
            call Sd_echo("unkown direction!")
          endif
        endfunction
      ]])
		end,
		keys = {
			-- { "ii", "<Plug>(indent-object_blockwise-none)",           mode = {"o"}},
			{ "ii", "<Plug>(indent-object_linewise-none)", mode = { "x", "o" } },
			{ "ai", "<Plug>(indent-object_linewise-start)", mode = { "x", "o" } },
			{ "aa", "<Plug>(indent-object_linewise-both)", mode = { "x", "o" } },
			--
			{ "ik", "<Plug>(indent-object_linewise-none-keep-end)", mode = { "x", "o" } },
			{ "ij", "<Plug>(indent-object_linewise-none-keep-start)", mode = { "x", "o" } },
			{ "[i", "<Plug>(indent-object_linewise-none-keep-end)", mode = { "x", "o" } },
			{ "]i", "<Plug>(indent-object_linewise-none-keep-start)", mode = { "x", "o" } },
			--
			{ "ak", "<Plug>(indent-object_linewise-start-keep-end)", mode = { "x", "o" } },
			{ "aj", "<Plug>(indent-object_linewise-end-keep-start)", mode = { "x", "o" } },
			{ "[a", "<Plug>(indent-object_linewise-start-keep-end)", mode = { "x", "o" } },
			{ "]a", "<Plug>(indent-object_linewise-end-keep-start)", mode = { "x", "o" } },
			{
				"[a",
				function()
					vim.fn.Sd_indent_move("top")
				end,
				mode = { "n" },
			},
			{
				"]a",
				function()
					vim.fn.Sd_indent_move("bottom")
				end,
				mode = { "n" },
			},
			{
				"[i",
				function()
					vim.fn.Sd_indent_move("up")
				end,
				mode = { "n" },
			},
			{
				"\\\\",
				function()
					vim.fn.Sd_indent_move("up")
				end,
				mode = { "n" },
			},
			{
				"]i",
				function()
					vim.fn.Sd_indent_move("down")
				end,
				mode = { "n" },
			},
			{
				"''",
				function()
					vim.fn.Sd_indent_move("down")
				end,
				mode = { "n" },
			},
		},
	},

	{
		"nvim-treesitter/nvim-treesitter",
		enabled = function()
			local check = vim.fn.executable("git")
			return check == 1
		end,
		keys = function()
			return {}
		end,
		opts = function()
			return {
				context_commentstring = { enable = true, enable_autocmd = true },
				matchup = {
					enable = false,
					disable = { "text", "ruby" },
				},
				indent = { enable = true, disable = {} },
				incremental_selection = {
					enable = false,
					keymaps = {
						init_selection = "<C-space>",
						node_incremental = "<C-space>",
						scope_incremental = "<nop>",
						node_decremental = "<bs>",
					},
				},
				highlight = {
					enable = true,
					disable = function(_, buf)
						local max_filesize = 300 * 1024
						local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
						if ok and stats and stats.size > max_filesize then
							return true
						end
					end,
					additional_vim_regex_highlighting = false,
				},
				textobjects = {
					select = {
						enable = false,
						lookahead = true,
						keymaps = {
							-- ["af"] = "@function.outer",
							-- ["if"] = "@function.inner",
							-- ["ac"] = "@class.outer",
							-- ["ic"] = { query = "@class.inner", desc = "Select inner part of a class region" },
						},
						--
						selection_modes = {
							["@function.outer"] = "V",
							["@function.inner"] = "V",
							["@class.outer"] = "V",
							["@class.inner"] = "V",
						},
						--
						include_surrounding_whitespace = false,
					},
					move = {
						enable = true,
						goto_next_start = {
							["]f"] = "@function.outer",
							-- ["]]"] = "@function.outer",
							["]c"] = "@class.outer",
							--
						},
						goto_next_end = {
							["]F"] = "@function.outer",
							["]C"] = "@class.outer",
						},
						goto_previous_start = {
							["[f"] = "@function.outer",
							-- ["[["] = "@function.outer",
							["[c"] = "@class.outer",
						},
						goto_previous_end = {
							["[F"] = "@function.outer",
							["[C"] = "@class.outer",
						},
					},
				},
				ensure_installed = {
					"bash",
					"c",
					"cmake",
					"css",
					"diff",
					"dockerfile",
					"dot",
					"go",
					"gomod",
					"gosum",
					"gowork",
					"hcl",
					"html",
					"ini",
					"javascript",
					"jsdoc",
					"json",
					"json5",
					"jsonc",
					"lua",
					"luadoc",
					"luap",
					"make",
					"markdown",
					"markdown_inline",
					"ninja",
					"printf",
					"python",
					"query",
					"regex",
					"rst",
					"terraform",
					"toml",
					"tsx",
					"typescript",
					"vim",
					"vimdoc",
					"xml",
					"yaml",
				},
			}
		end,
	},

	{
		"nvim-treesitter/nvim-treesitter-textobjects",
		enabled = function()
			local check = vim.fn.executable("git")
			return check == 1
		end,
	},

	{
		"windwp/nvim-ts-autotag",
		ft = { "javascript", "typescript", "html", "vue" },
		enabled = function()
			local check = vim.fn.executable("git")
			return check == 1
		end,
	},

	{
		"Wansmer/treesj",
		keys = {
			{
				"qss",
				mode = { "n" },
				function()
					require("treesj").toggle()
				end,
			},
			{
				"qJ",
				mode = { "n" },
				function()
					require("treesj").join()
				end,
				desc = "Join lines",
			},
			{
				"qS",
				mode = { "n" },
				function()
					require("treesj").split()
				end,
				desc = "Split lines",
			},
		},
		dependencies = { "nvim-treesitter/nvim-treesitter" },
		config = function()
			require("treesj").setup({
				use_default_keymaps = false,
				check_syntax_error = true,
				max_join_length = 512,
				cursor_behavior = "start",
				notify = true,
				dot_repeat = false,
			})
		end,
	},

	{
		"lambdalisue/suda.vim",
		keys = {
			{
				"QW",
				mode = { "n" },
				"<cmd>SudaWrite<cr>",
			},
			{
				"<leader>QW",
				mode = { "n" },
				"<cmd>SudaRead<cr>",
			},
		},
		cmd = { "SudaRead", "SudaWrite" },
	},

	{
		"NStefan002/screenkey.nvim",
		lazy = false,
		version = "*", -- or branch = "dev", to use the latest commit
	},

	{
		"gbprod/yanky.nvim",
		opts = {
			ring = {
				history_length = 20,
				storage = "memory",
				sync_with_numbered_registers = true,
				cancel_event = "update",
			},
			picker = {
				select = {
					action = nil,
				},
				telescope = {
					use_default_mappings = true,
					mappings = nil,
				},
			},
			system_clipboard = {
				sync_with_ring = false,
			},
			highlight = {
				on_put = true,
				on_yank = true,
				timer = 120,
			},
			preserve_cursor_position = {
				enabled = true,
			},
		},
		keys = function()
			return {
				{
					"y",
					"<Plug>(YankyYank)",
					mode = { "n", "x" },
					desc = "Yank text",
				},
				{
					"p",
					"<Plug>(YankyPutAfter)",
					mode = { "n", "x" },
					desc = "Put yanked text after cursor",
				},
				{
					"P",
					"<Plug>(YankyPutBefore)",
					mode = { "n", "x" },
					desc = "Put yanked text before cursor",
				},
				{
					"<c-n>",
					"<Plug>(YankyCycleBackward)",
					mode = { "n" },
					desc = "Cycle backward through yank history",
				},
				{
					"<c-p>",
					"<Plug>(YankyCycleForward)",
					mode = { "n" },
					desc = "Cycle forward through yank history",
				},
				{
					"<Down>",
					"<Plug>(YankyCycleBackward)",
					mode = { "n" },
					desc = "Cycle backward through yank history",
				},
				{
					"<Up>",
					"<Plug>(YankyCycleForward)",
					mode = { "n" },
					desc = "Cycle forward through yank history",
				},
				--
				-- {
				--  "]P",
				--  "<Plug>(YankyPutIndentAfterLinewise)",
				--  desc = "Put indented after cursor (linewise)",
				-- },
				-- {
				--  "[P",
				--  "<Plug>(YankyPutIndentBeforeLinewise)",
				--  desc = "Put indented before cursor (linewise)",
				-- },
				{
					"<leader><leader>p",
					"<Plug>(YankyPutIndentAfterLinewise)",
					desc = "Put indented after cursor (linewise)",
				},
				--
				{
					"<leader><leader>u",
					"<Plug>(YankyPutIndentBeforeCharwise)",
					desc = "Put indented before cursor (linewise)",
				},
				{
					"<leader><leader>U",
					"<Plug>(YankyPutIndentBeforeCharwise)a<space><esc>",
					desc = "Put indented before cursor (linewise)(insert space)",
				},
				--
				{
					"<leader><leader>i",
					"<Plug>(YankyPutIndentAfterCharwise)",
					desc = "Put indented after cursor (linewise)",
				},
				{
					"<leader><leader>I",
					"a<space><esc><Plug>(YankyPutIndentAfterCharwise)",
					desc = "Put indented after cursor (linewise)(insert space)",
				},
				{ "yp", "<cmd>normal yyp<cr>" },
			}
		end,
	},

	{
		"echasnovski/mini.hipatterns",
		event = "VeryLazy",
		opts = function()
			local hi = require("mini.hipatterns")
			return {
				tailwind = {
					enabled = true,
					ft = { "typescriptreact", "javascriptreact", "css", "javascript", "typescript", "html" },
					style = "full",
				},
				highlighters = {
					strongmark = { pattern = "!!!%s.+", group = "StrongMark" },
					strongmark_sub01 = { pattern = "!!@%s.+", group = "StrongMarkSub01" },
					strongmark_sub02 = { pattern = "!!#%s.+", group = "StrongMarkSub02" },
					whitespace = { pattern = "%s+$", group = "WhiteSpaceEOL" },
					note = { pattern = "@NOTE%f[%W]", group = "NormalNote" },
					todo = { pattern = "@TODO%f[%W]", group = "NormalNoteTODO" },
					debug = { pattern = "@DEBUG%f[%W]", group = "NormalNote" },
					delete = { pattern = "@DELETE%f[%W]", group = "NormalNote" },
					temp = { pattern = "@TEMP%f[%W]", group = "NormalNote" },
					fixme = { pattern = "@FIXME%f[%W]", group = "StrongNote" },
					mark = { pattern = "@MARK%f[%W]", group = "StrongNote" },
					url02 = { pattern = "()https?://%S+[^\"'%s]().*$", group = "httpURL" },
					hex_color = hi.gen_highlighter.hex_color({}),
				},
			}
		end,
	},

	{
		"akinsho/bufferline.nvim",
		keys = function()
			return {
				{ "<localleader>bb", "<Cmd>BufferLineCloseOthers<CR>", desc = "Delete other buffers" },
				{ "<localleader>bl", "<Cmd>BufferLineCloseRight<CR>", desc = "Delete buffers to the right" },
				{ "<localleader>bh", "<Cmd>BufferLineCloseLeft<CR>", desc = "Delete buffers to the left" },
				{ "(", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev buffer" },
				{ ")", "<cmd>BufferLineCycleNext<cr>", desc = "Next buffer" },
				{ "gh", "<cmd>BufferLineMovePrev<cr>", desc = "Move buffer left" },
				{ "gl", "<cmd>BufferLineMoveNext<cr>", desc = "Move buffer right" },
				{
					"<leader>1",
					function()
						require("bufferline").go_to(1, true)
					end,
				},
				{
					"<leader>2",
					function()
						require("bufferline").go_to(2, true)
					end,
				},
				{
					"<leader>3",
					function()
						require("bufferline").go_to(3, true)
					end,
				},
				{
					"<leader>4",
					function()
						require("bufferline").go_to(4, true)
					end,
				},
				{
					"<leader>5",
					function()
						require("bufferline").go_to(5, true)
					end,
				},
				{
					"<leader>6",
					function()
						require("bufferline").go_to(6, true)
					end,
				},
				{
					"<leader>7",
					function()
						require("bufferline").go_to(7, true)
					end,
				},
				{
					"<leader>8",
					function()
						require("bufferline").go_to(8, true)
					end,
				},
				{
					"<leader>9",
					function()
						require("bufferline").go_to(9, true)
					end,
				},
				{
					"<leader>0",
					function()
						require("bufferline").go_to(0, true)
					end,
				},
			}
		end,
		event = "VeryLazy",
		opts = function()
			local bf = require("bufferline")
			return {
				highlights = {
					tab_separator_selected = {
						fg = "#262a35",
						bg = "#262a35",
						sp = "#262a35",
						-- underline = "#262a35",
					},
					tab_separator = {
						fg = "#262a35",
						bg = "#262a35",
					},
					tab_selected = {
						fg = "yellow",
					},
				},
				options = {
					-- style_preset = bf.style_preset.default, -- or bufferline.style_preset.minimal,
					style_preset = bf.style_preset.minimal, -- or bufferline.style_preset.minimal,
					always_show_bufferline = true,
					persist_buffer_sort = true,
					modified_icon = "*",
					close_icon = "",
					truncate_names = false,
					diagnostics = false,
					diagnostics_update_in_insert = false,
					color_icons = false,
					show_buffer_icons = false,
					show_buffer_close_icons = false,
					show_close_icon = false,
					show_tab_indicators = true,
					show_duplicate_prefix = false,
					separator_style = { "", "" },
					-- separator_style = "slant" | "slope" | "thick" | "thin" | { 'any', 'any' },
					-- separator_style = "slant", --| "thick" | "thin" | { 'any', 'any' },
					max_prefix_length = 18,
					tab_size = 12,
					max_name_length = 18,
					-- left_trunc_marker = "",
					-- right_trunc_marker = "",
					indicator = { style = "none" },
					-- custom_filter = function(buf_number, buf_numbers)
					--   if vim.fn.bufname(buf_number) ~= "" then
					--     return true
					--   end
					-- end,
					enforce_regular_tabs = true,
					hover = {
						enabled = false,
						delay = 200,
						reveal = { "close" },
					},
					numbers = "ordinal",
					-- numbers = function(opts)
					--   return string.format("%s|%s", opts.id, opts.raise(opts.ordinal))
					-- end,
					offsets = {
						{
							filetype = "neo-tree",
							text = "Neo-tree",
							highlight = "Directory",
							text_align = "left",
						},
					},
					-- groups = {
					--   items = {
					--     require("bufferline.groups").builtin.pinned:with({ icon = "" }),
					--     -- 🧷 󰐃  󰤱
					--   },
					-- },
				},
			}
		end,
		-- config = function(_, opts)
		--   local bf = require("bufferline")
		--   bf.setup(opts)
		--   vim.api.nvim_create_autocmd("BufAdd", {
		--     callback = function()
		--       vim.schedule(function()
		--         pcall(nvim_bufferline)
		--       end)
		--     end,
		--   })
		-- end,
	},

	{
		"rcarriga/nvim-notify",
		-- lazy = false,
		opts = {
			background_colour = "#000000",
			-- background_colour = "Normal",
			timeout = 2000,
			max_height = function()
				return math.floor(vim.o.lines * 0.75)
			end,
			max_width = function()
				return math.floor(vim.o.columns * 0.4)
			end,
			fps = 10,
			icons = {
				DEBUG = "",
				ERROR = "",
				INFO = "",
				TRACE = "✎",
				WARN = "",
			},
			level = 2,
			-- render = "minimal",
			render = "wrapped-compact",
			stages = "fade",
		},
		keys = function()
			return {}
		end,
	},

	{
		"folke/noice.nvim",
		event = "VeryLazy",
		version = "*",
		keys = function()
			return {}
		end,
		-- keys = nil,
		opts = {
			routes = {
				{
					filter = {
						event = "msg_show",
						any = {
							-- { find = "Format provider not found for buffer:" },
							{ find = "%d+L, %d+B" },
							{ find = "; after #%d+" },
							{ find = "; before #%d+" },
							{ find = "Failed to load python3 host." },
							{ find = "--No lines in buffer--" },
							{ find = "Mark not set" },
							{ find = "Error executing vim.schedule lua callback" },
							{ find = "stack traceback:" },
							{ find = "Invalid window id:" },
						},
					},
					view = nil,
				},
			},
			cmdline = {
				enabled = true,
				view = "cmdline_popup",
				opts = {
					relative = "editor",
					position = {
						col = "50%",
						row = 4,
					},
					size = {
						width = "50%",
						height = "auto",
					},
					anchor = "NW",
					border = {
						style = "single",
						padding = {
							top = 0,
							bottom = 0,
							left = 0,
							right = 0,
						},
					},
				},
				format = {
					-- cmdline = false,
					-- search_down = false,
					-- search_up = false,
					filter = false,
					lua = false,
					help = false,
					-- input = {},
				},
			},
			messages = {
				enabled = true,
				view = "notify",
				view_error = "notify",
				view_warn = "notify",
				view_history = "messages",
				view_search = false,
			},
			presets = {
				bottom_search = false,
				command_palette = true,
				long_message_to_split = true,
				inc_rename = false,
				lsp_doc_border = false,
			},
			notify = {
				backend = "notify",
				fallback = "mini",
				format = "notify",
				replace = true,
				merge = true,
				enabled = false,
			},
		},
	},

	{
		"akinsho/toggleterm.nvim",
		dependencies = {
			"willothy/flatten.nvim",
		},
		cmd = {
			"ToggleTerm",
			"TermExec",
			"ToggleTermSetName",
			"ToggleTermToggleAll",
			"ToggleTermSendVisualLines",
			"ToggleTermSendCurrentLine",
			"ToggleTermSendVisualSelection",
		},
		keys = function()
			return {
				{ "<f1>", mode = { "n", "i" } },
				{ "<f2>", mode = { "n", "i" } },
				{ "<f3>", mode = { "n", "i" } },
				{ "<f4>", mode = { "n", "i" } },
				{ "<leader>\\", mode = { "n", "v" } },
				{ "<localleader>py", mode = { "n", "v" } },
				{ "<localleader>pu", mode = { "n", "v" } },
				{ "<localleader>pi", mode = { "n", "v" } },
				{ "<localleader>p\\", mode = { "n", "v" } },
				{ "<localleader>p//", mode = { "n", "v" } },
				{ "<localleader>\\", mode = { "n", "v" } },
				{ "<localleader>/", mode = { "n", "v" } },
				{ "<localleader>tt", mode = { "n", "v" } },
			}
		end,
		opts = {
			version = "*",
			config = true,
			direction = "float",
			start_in_insert = true,
			shade_terminals = true,
			persist_mode = false,
			float_opts = {
				title_pos = "left",
				border = "curved",
			},
			-- shell = function()
			--   local uname = vim.loop.os_uname()
			--   local os = uname.sysname
			--   if os:find("Windows") then
			--     return "nu.exe"
			--   else
			--     return vim.o.shell
			--   end
			-- end,
			size = function(term)
				if term.direction == "horizontal" then
					return 40
				elseif term.direction == "vertical" then
					return vim.o.columns * 0.5
				end
			end,
		},
		config = function(_, opts)
			require("toggleterm").setup(opts)
			vim.cmd([[
        function Sd_quick_toggleterm() abort
          if &ft == 'toggleterm'
          exe "ToggleTerm"
          else
          " normal! \<esc>
          silent! exe "norm! \<esc>"
          lua Snacks.notifier.hide()
        endif
        endfunction
        nnoremap <silent> <esc> :call Sd_quick_toggleterm()<CR>

        function Sd_toggle_window(n) abort
          let name =  'window-' . a:n
          exe a:n . 'ToggleTerm  name=' .  name . '  direction=float'
        endfunction

        nnoremap <silent> <f1> :call Sd_toggle_window(1)<CR>
        inoremap <silent> <f1> <ESC>:call Sd_toggle_window(1)<CR>
        tnoremap <silent> <f1> <C-\><C-n>:call Sd_toggle_window(1)<CR>
        nnoremap <silent> <f2> :call Sd_toggle_window(2)<CR>
        inoremap <silent> <f2> <ESC>:call Sd_toggle_window(2)<CR>
        tnoremap <silent> <f2> <C-\><C-n>:call Sd_toggle_window(2)<CR>
        nnoremap <silent> <f3> :call Sd_toggle_window(3)<CR>
        inoremap <silent> <f3> <ESC>:call Sd_toggle_window(3)<CR>
        tnoremap <silent> <f3> <C-\><C-n>:call Sd_toggle_window(3)<CR>
        nnoremap <silent> <f4> :call Sd_toggle_window(4)<CR>
        inoremap <silent> <f4> <ESC>:call Sd_toggle_window(4)<CR>
        tnoremap <silent> <f4> <C-\><C-n>:call Sd_toggle_window(4)<CR>

        nnoremap <silent><localleader>tt <Cmd>exe "9ToggleTerm direction=vertical size=120"<CR>
        vnoremap <silent><localleader>tt <Esc><Cmd>exe v:count1 . "9ToggleTerm direction=vertical size=180"<CR>
        nnoremap <silent><localleader>\ <Cmd>exe "9ToggleTerm direction=vertical size=120"<CR>
        vnoremap <silent><localleader>\ <Esc><Cmd>exe v:count1 . "9ToggleTerm direction=vertical size=180"<CR>
        nnoremap <silent><localleader>/ <Cmd>exe "8ToggleTerm direction=horizontal"<CR>
        vnoremap <silent><localleader>/ <Esc><Cmd>exe v:count1 . "8ToggleTerm direction=horizontal"<CR>
        " :ToggleTerm size=40 dir=~/Desktop direction=horizontal name=desktop
        " nnoremap <silent><localleader>\ :ToggleTerm direction=vertical<CR>
        nnoremap <silent> <leader>\ :ToggleTermSendCurrentLine<cr>
        vnoremap <silent> <leader>\ :ToggleTermSendVisualSelection<cr>

        nnoremap <silent><localleader>py <Cmd>exe "7ToggleTerm direction=horizontal"<CR>
        vnoremap <silent><localleader>py <Esc><Cmd>exe v:count1 . "7ToggleTerm direction=horizontal"<CR>
        nnoremap <silent><localleader>pu <Cmd>exe "8ToggleTerm direction=horizontal"<CR>
        vnoremap <silent><localleader>pu <Esc><Cmd>exe v:count1 . "8ToggleTerm direction=horizontal"<CR>
        nnoremap <silent><localleader>pi <Cmd>exe "9ToggleTerm direction=horizontal"<CR>
        vnoremap <silent><localleader>pi <Esc><Cmd>exe v:count1 . "9ToggleTerm direction=horizontal"<CR>

        nnoremap <silent><localleader>p\ :resize +15<CR>
        vnoremap <silent><localleader>p\ <Esc>:resize +15<CR>
        nnoremap <silent><localleader>p/ :resize -15<CR>
        vnoremap <silent><localleader>p/ <Esc>:resize -15<CR>
        ]])
		end,
	},

	{
		"jbyuki/venn.nvim",
		init = function()
			vim.cmd([[
        function! Sd_prepare_file_for_draw()
          normal mtG
          if line("$") < 20
            while line('$') <= 35
              exe ':$put _'
            endwhile
          endif
          normal `t
        endfunction

        let g:sd_diagram_cornor = [ '┌', '┘', '└', '┌' ]
        let g:sd_diagram_cross = [ '┴', '┬', '┤', '├', '┼' ] + g:sd_diagram_cornor
        function! Sd_create_dash_for_diagram(...)
          if a:0 == 0
            if Sd_get_charactor_under_cursor() == '─'
              normal e
              if Sd_get_charactor_under_cursor() == '┐'
                normal j
                while Sd_get_charactor_under_cursor() == '│'
                  normal j
                endwhile
              endif
            elseif Sd_get_charactor_under_cursor() == '┐'
              normal j
              while Sd_get_charactor_under_cursor() == '│'
                normal j
              endwhile
            elseif Sd_get_charactor_under_cursor() == '┌'
              normal ej
              while Sd_get_charactor_under_cursor() == '│'
                normal j
              endwhile
            elseif Sd_get_charactor_under_cursor() == '└'
              normal e
            elseif Sd_get_charactor_under_cursor() == '│'
              while Sd_get_charactor_under_cursor() == '│'
                normal j
              endwhile
              if Sd_get_charactor_under_cursor() == '└'
                normal e
              endif
            else
              call Sd_echo("Error! unable using initial cursor position to location the diagrams right-down cornor! ")
              return
            endif
            if Sd_get_charactor_under_cursor() != '┘'
              call Sd_echo("Error! looks like the curosr is not on a diagrams!")
              return
            endif

            normal k
            let l:step_count = 0
            while Sd_get_charactor_under_cursor() != '┐'
              if l:step_count % 2 == 0
                exe 'normal! r '
              endif
              normal k
              let l:step_count += 1
            endwhile

            normal h
            let l:step_count = 0
            while Sd_get_charactor_under_cursor() != '┌'
              if l:step_count % 2 == 0
                exe 'normal! r '
              endif
              normal h
              let l:step_count += 1
            endwhile

            normal j
            let l:step_count = 0
            while Sd_get_charactor_under_cursor() != '└'
              if l:step_count % 2 == 0
                exe 'normal! r '
              endif
              let l:step_count += 1
              normal j
            endwhile

            normal l
            let l:step_count = 0
            while Sd_get_charactor_under_cursor() != '┘'
              if l:step_count % 2 == 0
                exe 'normal! r '
              endif
              let l:step_count += 1
              normal l
            endwhile

            " echo index(g:sd_diagram_cornor, matchstr(getline('.'), '\%' . col('.') . 'c.'))
          else
            if a:1 == 'line'
              if Sd_get_charactor_under_cursor() == '─'
                normal bl
                let l:step_count = 0
                let l:temp_list = g:sd_diagram_cross + ['─']
                while index(l:temp_list, Sd_get_charactor_under_cursor()) >= 0
                  if l:step_count % 2 == 0
                    exe 'normal! r '
                  endif
                  let l:step_count += 1
                  normal l
                endwhile
              elseif Sd_get_charactor_under_cursor() == '│'

                let l:temp_list = g:sd_diagram_cross + ['│']
                while index(l:temp_list, Sd_get_charactor_under_cursor()) >= 0
                  normal k
                endwhile

                let l:step_count = 0
                normal j
                while index(l:temp_list, Sd_get_charactor_under_cursor()) >= 0
                  if l:step_count % 2 == 0
                    exe 'normal! r '
                  endif
                  let l:step_count += 1
                  normal j
                endwhile

              endif
            endif
          endif
        endfunction

        function! Sd_venn_mode_toggle()
          if ! exists("b:venn_enable")
            let b:venn_enable = 0
          endif
          if b:venn_enable == 0
            call Sd_prepare_file_for_draw()
            setlocal virtualedit=all
            nnoremap <silent> <buffer> J <C-v>j:VBox<CR>
            nnoremap <silent> <buffer> K <C-v>k:VBox<CR>
            nnoremap <silent> <buffer> L <C-v>l:VBox<CR>
            nnoremap <silent> <buffer> H <C-v>h:VBox<CR>
            vnoremap <silent> <buffer> f :VBox<CR>

            vnoremap <silent> <buffer> <m-s-k> dkhp:call Sd_reselect_last_paste_block()<CR>
            vnoremap <silent> <buffer> <m-s-j> djhp:call Sd_reselect_last_paste_block()<CR>
            vnoremap <silent> <buffer> <m-s-l> dlp:call  Sd_reselect_last_paste_block()<CR>
            vnoremap <silent> <buffer> <m-s-h> dhhp:call Sd_reselect_last_paste_block()<CR>

            nnoremap <silent> <buffer> <leader>l g_

            nnoremap <silent> <buffer> <leader>d :call Sd_create_dash_for_diagram()<CR>
            nnoremap <silent> <buffer> <leader>D :call Sd_create_dash_for_diagram('line')<CR>

            setlocal list

            let l:reg_f="┌─────┐". "\n". "│ r1  │". "\n" . "└─────┘"
            call setreg('f', l:reg_f, 'b')
            let l:reg_r="┌─────┐". "\n". "│ s1  │". "\n" . "└─────┘"
            call setreg('r', l:reg_r, 'b')

            echo 'enable venn, Draw mode on'
          else
            setlocal list!
            setlocal virtualedit=insert,block
            exe "mapclear <buffer>"
            echo 'disable venn, Draw mode off'
          endif
          let b:venn_enable = b:venn_enable == 0 ? 1 : 0
        endfunction
        " nnoremap <silent> <leader>V :call Sd_venn_mode_toggle()<CR>
      ]])
		end,
		keys = {
			{
				"<leader>V",
				function()
					vim.cmd([[call Sd_venn_mode_toggle()]])
				end,
				mode = "n",
			},
		},
	},

	{
		"ziontee113/color-picker.nvim",
		cmd = {
			"PickColor",
			"PickColorInsert",
		},
		opts = {
			-- for changing icons & mappings
			["icons"] = { "ﱢ", "" },
			-- ["icons"] = { "ﮊ", "" },
			-- ["icons"] = { "", "ﰕ" },
			-- ["icons"] = { "", "" },
			-- ["icons"] = { "", "" },
			-- ["icons"] = { "ﱢ", "" },
			["border"] = "rounded", -- none | single | double | rounded | solid | shadow
			["keymap"] = { -- mapping example:
				["U"] = "<Plug>ColorPickerSlider5Decrease",
				["O"] = "<Plug>ColorPickerSlider5Increase",
			},
			["background_highlight_group"] = "Normal", -- default
			["border_highlight_group"] = "FloatBorder", -- default
			["text_highlight_group"] = "Normal", --default
		},
		keys = {
			{ "<leader>cp", mode = "n", "<cmd>PickColor<cr>" },
			-- { "<leader>:", "<cmd>Telescope command_history<cr>", desc = "Command History" },
		},
	},

	{
		"Pocco81/HighStr.nvim",
		-- event='VeryLazy',
		keys = {
			{
				"<leader><leader><backspace>",
				"<esc><cmd>HSRmHighlight<CR>",
				mode = { "v" },
			},
			{
				"<leader><leader><backspace>",
				"<esc>viw<esc><cmd>HSRmHighlight<CR>",
				mode = { "n" },
			},
			{ "<leader><leader>1", "vawo<esc><cmd>HSHighlight 1<CR>", mode = { "n" } },
			{ "<leader><leader>1", "<esc><cmd>HSHighlight 1<CR>", mode = { "v" } },
			{ "<leader><leader>2", "vawo<esc><cmd>HSHighlight 2<CR>", mode = { "n" } },
			{ "<leader><leader>2", "<esc><cmd>HSHighlight 2<CR>", mode = { "v" } },
			{ "<leader><leader>3", "vawo<esc><cmd>HSHighlight 3<CR>", mode = { "n" } },
			{ "<leader><leader>3", "<esc><cmd>HSHighlight 3<CR>", mode = { "v" } },
			{ "<leader><leader>4", "vawo<esc><cmd>HSHighlight 4<CR>", mode = { "n" } },
			{ "<leader><leader>4", "<esc><cmd>HSHighlight 4<CR>", mode = { "v" } },
		},
		opts = {
			verbosity = 0,
			saving_path = "/tmp/highstr/",
			highlight_colors = {
				-- color_id = {"bg_hex_code",<"fg_hex_code"/"smart">}
				color_0 = { "#0c0d0e", "smart" }, -- Cosmic charcoal
				color_1 = { "#7FFFD4", "smart" }, -- Aqua menthe
				color_2 = { "#8A2BE2", "smart" }, -- Proton purple
				color_3 = { "#FF4500", "smart" }, -- Orange red
				color_4 = { "#008000", "smart" }, -- Office green
				color_5 = { "#e5c07b", "smart" }, -- Pastel yellow
				color_6 = { "#0000FF", "smart" }, -- Just blue
				color_7 = { "#FFC0CB", "smart" }, -- Blush pink
				color_8 = { "#FFF9E3", "smart" }, -- Cosmic latte
				color_9 = { "#7d5c34", "smart" }, -- Fallow brown
			},
		},
	},

	{
		"willothy/flatten.nvim",
		config = true,
		lazy = false,
		-- priority = 1001,
		opts = {
			nest_if_no_args = true,
			window = {
				open = "alternate",
			},
		},
	},

	{
		"b0o/incline.nvim",
		event = "VeryLazy",
		config = function()
			require("incline").setup({
				hide = {
					cursorline = false,
					focused_win = true,
					only_win = true,
				},
				render = function(props)
					local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t")
					local ft_icon, ft_color = require("nvim-web-devicons").get_icon_color(filename)
					local modified = vim.bo[props.buf].modified and "bold,italic" or "bold"

					return {
						{ (ft_icon or "") .. " ", guifg = ft_color, guibg = "none" },
						{ filename, gui = modified },
						-- { '┊  ' .. vim.api.nvim_win_get_number(props.win), group = 'DevIconWindows' },
					}
				end,
			})
		end,
	},

	{
		"MeanderingProgrammer/render-markdown.nvim",
		ft = { "markdown" },
		opts = {
			heading = {
				-- Turn on / off heading icon & background rendering
				enabled = true,
				-- Turn on / off any sign column related rendering
				sign = false,
				-- Determines how icons fill the available space:
				--  inline:  underlying '#'s are concealed resulting in a left aligned icon
				--  overlay: result is left padded with spaces to hide any additional '#'
				position = "overlay",
				-- Replaces '#+' of 'atx_h._marker'
				-- The number of '#' in the heading determines the 'level'
				-- The 'level' is used to index into the array using a cycle
				icons = { "󰲡 ", "󰲣 ", "󰲥 ", "󰲧 ", "󰲩 ", "󰲫 " },
				-- Added to the sign column if enabled
				-- The 'level' is used to index into the array using a cycle
				signs = { "󰫎 " },
				-- Width of the heading background:
				--  block: width of the heading text
				--  full:  full width of the window
				-- Can also be an array of the above values in which case the 'level' is used
				-- to index into the array using a clamp
				width = "block",
				-- Amount of padding to add to the left of headings
				left_pad = 0,
				-- Amount of padding to add to the right of headings when width is 'block'
				right_pad = 0,
				-- Minimum width to use for headings when width is 'block'
				min_width = 0,
				-- Determins if a border is added above and below headings
				border = false,
				-- Highlight the start of the border using the foreground highlight
				border_prefix = false,
				-- Used above heading for border
				above = "▄",
				-- Used below heading for border
				below = "▀",
				-- The 'level' is used to index into the array using a clamp
				-- Highlight for the heading icon and extends through the entire line
				backgrounds = {
					"RenderMarkdownH1Bg",
					"RenderMarkdownH2Bg",
					"RenderMarkdownH3Bg",
					"RenderMarkdownH4Bg",
					"RenderMarkdownH5Bg",
					"RenderMarkdownH6Bg",
				},
				-- The 'level' is used to index into the array using a clamp
				-- Highlight for the heading and sign icons
				foregrounds = {
					"RenderMarkdownH1",
					"RenderMarkdownH2",
					"RenderMarkdownH3",
					"RenderMarkdownH4",
					"RenderMarkdownH5",
					"RenderMarkdownH6",
				},
			},
			code = {
				-- Turn on / off code block & inline code rendering
				enabled = true,
				-- Turn on / off any sign column related rendering
				sign = false,
				-- Determines how code blocks & inline code are rendered:
				--  none:     disables all rendering
				--  normal:   adds highlight group to code blocks & inline code, adds padding to code blocks
				--  language: adds language icon to sign column if enabled and icon + name above code blocks
				--  full:     normal + language
				style = "normal",
				-- Determines where language icon is rendered:
				--  right: right side of code block
				--  left:  left side of code block
				position = "left",
				-- Amount of padding to add around the language
				language_pad = 0,
				-- An array of language names for which background highlighting will be disabled
				-- Likely because that language has background highlights itself
				disable_background = { "diff" },
				-- Width of the code block background:
				--  block: width of the code block
				--  full:  full width of the window
				width = "block",
				-- Amount of padding to add to the left of code blocks
				left_pad = 0,
				-- Amount of padding to add to the right of code blocks when width is 'block'
				right_pad = 0,
				-- Minimum width to use for code blocks when width is 'block'
				min_width = 0,
				-- Determins how the top / bottom of code block are rendered:
				--  thick: use the same highlight as the code body
				--  thin:  when lines are empty overlay the above & below icons
				border = "thin",
				-- Used above code blocks for thin border
				above = "▄",
				-- Used below code blocks for thin border
				below = "▀",
				-- Highlight for code blocks
				highlight = "RenderMarkdownCode",
				-- Highlight for inline code
				highlight_inline = "RenderMarkdownCodeInline",
			},
		},
		-- dependencies = { "nvim-treesitter/nvim-treesitter", "echasnovski/mini.nvim" }, -- if you use the mini.nvim suite
		dependencies = { "nvim-treesitter/nvim-treesitter", "echasnovski/mini.icons" }, -- if you use standalone mini plugins
		-- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, -- if you prefer nvim-web-devicons
	},

	{
		"fei6409/log-highlight.nvim",
		ft = { "log" },
		config = function()
			require("log-highlight").setup({})
		end,
	},

	{
		"dstein64/vim-startuptime",
		cmd = "StartupTime",
		config = function()
			vim.g.startuptime_tries = 10
			-- Check the OS and set the template directory accordingly
			if vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 then
				vim.g.sd_template_dir = vim.g.sd_vim_dir .. "/seadog_files/templates/"
			else
				vim.g.sd_template_dir = vim.g.sd_vim_dir .. "/templates/"
			end
			function Sd_compress_whitespace(x)
				local mode = vim.fn.visualmode()

				local insert_space = ""
				if x > 0 then
					insert_space = string.rep(" ", x)
				end

				if mode == "v" then
					-- 获取视觉模式的选择范围
					-- local start_pos, end_pos = vim.fn.getpos("'<"), vim.fn.getpos("'>")
					-- print("Visual selection start: " .. vim.inspect(start_pos))
					-- print("Visual selection end: " .. vim.inspect(end_pos))
					-- Get the current visual selection range
					local _, start_line, start_col, _ = unpack(vim.fn.getpos("'<"))
					local _, end_line, end_col, _ = unpack(vim.fn.getpos("'>"))

					local lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, true)

					-- print(start_line, end_line)
					if start_line == end_line then
						local line = lines[1]
						local selected_content = line:sub(start_col, end_col)
						local compressed_content = selected_content:gsub("%s+", insert_space)
						line = line:sub(1, start_col - 1) .. compressed_content .. line:sub(end_col)
						vim.api.nvim_buf_set_lines(0, start_line - 1, start_line, false, { line })
					else
						local new_lines = {}

						-- Process the first line separately
						local first_line = lines[1]
						local first_selected = first_line:sub(start_col)
						local first_compressed = first_selected:gsub("%s+", insert_space)
						new_lines[1] = first_line:sub(1, start_col - 1) .. first_compressed

						-- Process all whole lines in between
						for i = 2, #lines - 1 do
							new_lines[i] = lines[i]:gsub("%s+", insert_space)
						end

						-- Process the last selected line
						local last_line = lines[#lines]
						local last_selected = last_line:sub(1, end_col)
						local last_compressed = last_selected:gsub("%s+", insert_space)
						new_lines[#lines] = last_compressed .. last_line:sub(end_col + 1)

						-- print(new_lines[#lines])
						vim.api.nvim_buf_set_lines(0, start_line - 1, end_line, false, new_lines)
					end
				elseif mode == "V" then
					local _, start_line, _, _ = unpack(vim.fn.getpos("'<"))
					local _, end_line, _, _ = unpack(vim.fn.getpos("'>"))
					local lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, true)
					local new_lines = {}

					for i = 1, #lines do
						local line = lines[i]
						local leading_spaces = ""
						for j = 1, #line do
							if line:sub(j, j) ~= " " then
								break
							end
							leading_spaces = " " .. leading_spaces
						end
						line = line:match("%s*(.*)")
						new_lines[i] = leading_spaces .. line:gsub("%s+", insert_space)
					end
					vim.api.nvim_buf_set_lines(0, start_line - 1, end_line, false, new_lines)
				elseif mode == "\22" then -- block-wise
					local _, start_line, start_col, _ = unpack(vim.fn.getpos("'<"))
					local _, end_line, end_col, _ = unpack(vim.fn.getpos("'>"))

					if start_col == end_col then
						return
					end

					if start_col > end_col then
						start_col, end_col = end_col, start_col
					end
					if start_line > end_line then
						start_line, end_line = end_line, start_line
					end

					-- print(start_line, start_col, end_line, end_col)
					-- print(start_line, end_line)
					local lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, true)

					for i = 1, #lines do
						local line = lines[i]
						if start_col < #line then
							local start_pos = start_col
							local end_pos = (end_col <= #line) and end_col or #line

							local content_to_compress = line:sub(start_pos, end_pos)
							local compressed_content = content_to_compress:gsub("%s+", insert_space)
							line = line:sub(1, start_pos - 1) .. compressed_content .. line:sub(end_pos + 1)

							lines[i] = line
						end
					end

					vim.api.nvim_buf_set_lines(0, start_line - 1, end_line, false, lines)
				else
					LazyVim.notify("Unkown visual mode", {
						title = "Unkown visual mode",
						level = 3,
					})
				end
			end
			vim.cmd("source ~/.config/nvim/lazy_sd_function.vim")
		end,
		keys = {
			{
				"<leader>ss",
				mode = { "n" },
				function()
					vim.cmd('silent! exec "lua Lazy reload LazyVim"')
					if vim.g.hostname == "apple" then
						vim.cmd("hi! Folded ctermbg=NONE guibg=NONE guifg=#6c7d9c")
					else
						-- grubox
						vim.cmd("hi! Folded ctermbg=NONE guibg=NONE guifg=#CABD9A")
					end
					vim.cmd("hi! MiniFilesCursorLine cterm=italic gui=italic guifg=#ffc777 guibg=#121212")
					vim.cmd("hi! MiniFilesTitleFocused ctermfg=204 guifg=#f55385")
					vim.cmd("hi! CursorLine ctermbg=16 cterm=NONE guibg=#121212")
				end,
				desc = "reload config",
			},
			{
				"QF",
				mode = { "n" },
				function()
					local choice = vim.fn.input("filetype > ", "", "filetype")

					if choice:match("^%s*$") or choice:match(".*\\<Esc>.*") or choice:match(".*\\<C-C>.*") then
						return
					end

					local choice_ft
					if vim.fn.index({ "m", "mk" }, choice) >= 0 then
						choice_ft = "markdown"
					elseif vim.fn.index({ "v", "vi" }, choice) >= 0 then
						choice_ft = "vim"
					elseif vim.fn.index({ "y", "yml" }, choice) >= 0 then
						choice_ft = "yaml"
					elseif vim.fn.index({ "l", "log" }, choice) >= 0 then
						choice_ft = "log"
					elseif vim.fn.index({ "t", "txt" }, choice) >= 0 then
						choice_ft = "text"
					elseif vim.fn.index({ "j", "json" }, choice) >= 0 then
						choice_ft = "json"
					elseif vim.fn.index({ "s", "b", "bash" }, choice) >= 0 then
						choice_ft = "sh"
					elseif vim.fn.index({ "p", "py" }, choice) >= 0 then
						choice_ft = "python"
					elseif vim.fn.index({ "an", "ansible" }, choice) >= 0 then
						vim.cmd("setlocal filetype=yaml.ansible")
						return
					else
						choice_ft = choice
					end
					vim.cmd("setlocal filetype=" .. choice_ft)
					vim.cmd("setlocal syntax=" .. choice_ft)
				end,
				desc = "quick switch ft or syn",
			},
			-- custom open file: gf
			{
				"<leader>gf",
				function()
					local file_path = sd_get_continuous_chars_under_cursor()

					if file_path then
						if vim.fn.has("win32") == 0 then
							if file_path:sub(1, 2) == "./" or file_path:sub(1, 3) == "../" then
								file_path = vim.fn.expand("%:p:h") .. "/" .. file_path
							end
						end

						if file_path:find("^~") then
							file_path = file_path:sub(2, #file_path)
							file_path = os.getenv("HOME") .. file_path
						end

						local start = string.find(file_path, '"') or string.find(file_path, "'")
						if start then
							file_path = string.sub(file_path, 1, start - 1)
						end

						if vim.fn.has("win32") == 0 then
							if not file_path:find("^/") then
								file_path = vim.fn.expand("%:p:h") .. "/" .. file_path
							end
						end
					end

					if file_path and vim.fn.filereadable(file_path) == 1 then
						vim.cmd("vs " .. file_path)
						LazyVim.notify(file_path, {
							title = "open file successfully",
							level = 2,
						})
					else
						vim.fn.setreg("p", file_path, "l")
						LazyVim.notify(file_path, {
							title = "unable open file, 'P'",
							level = 3,
						})
					end
				end,
				desc = "try to open a file",
			},
			-- cd / lcd
			{
				"<leader>cd",
				function()
					local dir = LazyVim.root()
					vim.api.nvim_command("lcd " .. dir)
					LazyVim.notify(dir, {
						title = "root directory",
						level = 2,
					})
				end,
				desc = "lcd root directory",
			},
			{
				"<leader><leader>cd",
				function()
					local dir = vim.fn.expand("%:p:h")
					if dir then
						vim.api.nvim_command("lcd " .. dir)
						LazyVim.notify(dir, {
							title = "current file directory",
							level = 2,
						})
					else
						LazyVim.notify("Failed to get current file directory", {
							title = "lcd current file directory",
							level = 4,
						})
					end
				end,
				desc = "lcd current file directory",
			},
			-- work with authohotkey, jump forward
			{
				"<c-m-i>",
				"<c-i>",
			},
			-- switch windows
			{
				"<m-q>",
				mode = { "n", "v", "t" },
				function()
					vim.api.nvim_command("wincmd h")
				end,
			},
			{
				"<m-w>",
				mode = { "n", "v", "t" },
				function()
					vim.api.nvim_command("wincmd l")
				end,
			},
			-- -- session
			-- { "<leader><leader>ss", mode = { "n" }, desc = "save session" },
			-- { "<leader><leader>ll", mode = { "n" }, desc = "load session" },
			-- quick-execution
			{
				"qc",
				mode = { "n" },
				function()
					Snacks.notifier.hide()
					if not vim.b.sd_quick_cmd then
						vim.b.sd_quick_cmd = 0
					end

					local file_path = vim.fn.expand("%:p")

					-- print(file_path:match("^term:"))
					-- print(string.find(str, "^term:"))
					-- if
					--   file_path:match("^term:.+//%d+:cd%s.*$")
					--   or file_path:match("^term://.+//%d+:.+%.py$")
					--   or file_path:match("^term://.+//%d+:.+%.sh$")
					--   or file_path:match(".*!(python|bash).*(py|sh)$")
					--   or file_path:match("^term://.+main-go")
					-- then
					if file_path:match("^term:") then
						vim.api.nvim_command("bd!")
						file_path = vim.fn.expand("%:p")
					end

					if
						not (
							vim.b.sd_quick_cmd
							or file_path:match("test_%w+%.py$")
							or vim.bo.filetype == "python"
							or vim.bo.filetype == "sh"
							or vim.bo.filetype == "go"
							or vim.bo.filetype == "c"
						)
					then
						LazyVim.notify("Not a .py/.sh/.go/.c file or Not execution-CMD !", {
							title = "failed to execute CMD",
							level = 3,
						})
						return
					end

					vim.api.nvim_command("call CloseAnyTermWindow02()")
					vim.api.nvim_command("wa")
					vim.api.nvim_command("lcd " .. LazyVim.root())
					if vim.b.sd_quick_cmd == 1 then
						vim.api.nvim_command("vs")
						local quick_cmd_file = vim.g.sd_vim_data_dir
							.. "/quick_cmd---"
							.. string.gsub(vim.fn.expand("%:p"), "/", "_")
							.. ".sh"
						if vim.bo.filetype == "go" then
							quick_cmd_file = vim.g.sd_vim_data_dir
								.. "/quick_cmd---"
								.. string.gsub(LazyVim.root(), "/", "_")
								.. ".sh"
						end
						vim.api.nvim_command("terminal bash " .. quick_cmd_file)
					elseif vim.bo.filetype == "yaml" then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("terminal " .. "ansible-playbook " .. file_path)
					elseif vim.bo.filetype == "sh" then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("terminal " .. "bash " .. file_path)
					elseif vim.bo.filetype == "c" then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("lcd %:p:h")
						vim.api.nvim_command("terminal gcc " .. file_path .. vim.g.sd_gcc_temp_dir)
					elseif file_path:match("_test.go$") then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("lcd %:p:h")
						vim.api.nvim_command("terminal go test")
					elseif vim.bo.filetype == "go" then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("terminal " .. "go build -o /tmp/main-go . && /tmp/main-go")
					elseif file_path:match("test_%w+%.py$") then
						vim.api.nvim_command("lcd %:p:h")
						vim.api.nvim_command("TermExec cmd=" .. '"python3 -m pytest ' .. file_path .. '."')
					elseif vim.bo.filetype == "python" then
						vim.api.nvim_command("vs")
						vim.api.nvim_command("terminal python3 %")
					else
						LazyVim.notify("Not a .py/.sh/.go/.c file or Not execution-CMD !", {
							title = "failed to execute CMD",
							level = 3,
						})
					end
				end,
				desc = "quick run",
			},
			{
				"QC",
				function()
					local original_filename = vim.fn.expand("%")
					local original_filepath = vim.fn.expand("%:p")
					local original_buf_ft = vim.bo.filetype
					if string.sub(original_filename, 1, 5) == "term:" then
						LazyVim.notify("terminal is not supported", {
							title = "quick_cmd_file",
							level = 4,
						})
						return
					end
					local original_buf = vim.api.nvim_get_current_buf()
					local quick_cmd_file = vim.g.sd_vim_data_dir
						.. "/quick_cmd---"
						.. string.gsub(original_filepath, "/", "_")
						.. ".sh"

					vim.api.nvim_buf_set_var(original_buf, "sd_quick_cmd", 0)

					local content = ""
					if original_buf_ft == "sh" then
						content = "bash " .. original_filepath
					elseif original_buf_ft == "go" then
						if string.match(original_filename, "_test.go$") then
							content = "go test"
						else
							quick_cmd_file = vim.g.sd_vim_data_dir
								.. "/quick_cmd---"
								.. string.gsub(LazyVim.root(), "/", "_")
								.. ".sh"
							content = "go build -o /tmp/main-go . && /tmp/main-go "
						end
					elseif original_buf_ft:sub(1, 4) == "yaml" then
						content = "ansible-playbook " .. original_filepath
					elseif original_buf_ft == "python" then
						if string.match(original_filename, "test_%w+%.py$") then
							content = "python -m pytest  " .. original_filepath .. " ."
						else
							content = "python3 " .. original_filepath
						end
					elseif original_buf_ft == "c" then
						content = ":terminal gcc " .. original_filepath .. vim.g.sd_gcc_temp_dir
					else
						content = ""
					end

					-- local floating_buf = vim.api.nvim_create_buf(false, true)
					-- Create or open the buffer associated with the file
					local floating_buf = vim.fn.bufnr(quick_cmd_file)
					if floating_buf == -1 then
						floating_buf = vim.api.nvim_create_buf(false, false) -- Create a new buffer if not found
						vim.api.nvim_buf_set_name(floating_buf, quick_cmd_file)
					end

					local width = math.floor(vim.o.columns * 3 / 5)
					local height = math.floor(vim.o.lines / 2)
					local win_opts = {
						relative = "editor",
						width = width,
						height = height,
						col = (vim.o.columns - width) / 2,
						row = (vim.o.lines - height) / 2,
						style = "minimal",
						border = "rounded",
					}

					-- Create a floating window
					local win = vim.api.nvim_open_win(floating_buf, true, win_opts)

					-- Set some options for better user experience
					-- vim.api.nvim_buf_set_option(floating_buf, "buftype", "nofile")
					vim.api.nvim_buf_set_option(floating_buf, "bufhidden", "hide")
					vim.api.nvim_buf_set_option(floating_buf, "filetype", "sh")

					-- Check if the file exists and load its content if it does
					local file = io.open(quick_cmd_file, "r") -- Open file for reading
					if file then
						content = file:read("*a") -- Read the whole file content
						file:close() -- Close the file when done
					end
					vim.api.nvim_buf_set_lines(floating_buf, 0, -1, false, vim.split(content, "\n")) -- Load content into the floating window
					vim.cmd("normal 0")
					-- vim.cmd("startinsert")

					function Close_and_execute()
						vim.api.nvim_command("silent! write!")

						vim.api.nvim_buf_set_var(original_buf, "sd_quick_cmd", 1)
						-- Get the command text from the buffer
						-- local command = vim.api.nvim_buf_get_lines(floating_buf, 0, -1, false)
						-- local command_string = table.concat(command, "\n")
						-- -- Save the command to the generated file path
						-- local file_out = io.open(quick_cmd_file, "w") -- Open file in append mode
						-- if file_out then
						--  file_out:write(command_string .. "\n") -- Write the command and a newline
						--  file_out:close() -- Close the file when done
						-- else
						--  print("Couldn't open file for writing!")
						-- end
						-- Close the floating window
						vim.api.nvim_win_close(win, true)
					end

					-- Set a key mapping to save and close the buffer
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"n",
						"FF",
						"<cmd>lua Close_and_execute()<CR>",
						{ noremap = true, silent = true }
					)
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"i",
						"FF",
						"<ESC><cmd>lua Close_and_execute()<CR>",
						{ noremap = true, silent = true }
					)
					-- Optionally, allow user to quit without saving
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"n",
						"QC",
						"<cmd>bd!<CR>",
						{ noremap = true, silent = true }
					)
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"n",
						"qq",
						"<cmd>bd!<CR>",
						{ noremap = true, silent = true }
					)
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"i",
						"<c-c>",
						"<esc><cmd>bd!<CR>",
						{ noremap = true, silent = true }
					)
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"n",
						"<c-c>",
						"<cmd>bd!<CR>",
						{ noremap = true, silent = true }
					)
					vim.api.nvim_buf_set_keymap(
						floating_buf,
						"n",
						"<esc>",
						"<cmd>bd!<CR>",
						{ noremap = true, silent = true }
					)
				end,
				desc = "original to open a file",
			},
			-- local yank, linux only
			{ "<leader>y", mode = { "n" } },
			{ "<leader>y", mode = { "v" } },
			{ "<leader>p", mode = { "n" } },
			-- quickly open a temporay file
			{ "<localleader>f", mode = { "n" } },
			{ "<localleader>f", mode = { "v" } },
			{ "<localleader>F", mode = { "n" } },
			-- line wrap toggle
			{
				"<leader>w",
				mode = { "n" },
				function()
					-- Toggle wrap
					vim.wo.wrap = not vim.wo.wrap

					if vim.wo.wrap then
						-- Set mappings when wrap is on
						vim.api.nvim_buf_set_keymap(0, "v", "<Leader>h", "g^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "<Leader>l", "g$", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "<Leader>h", "g^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "<Leader>l", "g$", { noremap = true, silent = true })

						-- Map j and k for visual and normal modes
						vim.api.nvim_buf_set_keymap(0, "n", "j", "gj", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "k", "gk", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "j", "gj", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "k", "gk", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "0", "g0", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "^", "g^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "$", "g$", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "0", "g0", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "^", "g^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "$", "g$", { noremap = true, silent = true })
					else
						-- Set mappings when wrap is off
						vim.api.nvim_buf_set_keymap(0, "v", "<Leader>h", "^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "<Leader>l", "$", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "<Leader>h", "^", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "<Leader>l", "$", { noremap = true, silent = true })

						-- Restore normal j and k behavior
						vim.api.nvim_buf_set_keymap(0, "n", "j", "j", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "n", "k", "k", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "j", "j", { noremap = true, silent = true })
						vim.api.nvim_buf_set_keymap(0, "v", "k", "k", { noremap = true, silent = true })
					end
				end,
				desc = "Toggle line wrap",
			},
			-- 插入文件头
			{
				"QT",
				mode = { "n" },
				"<cmd>call Sd_insert_template()<CR>",
				desc = "insert template header",
			},
			{
				"<c-s>",
				"<cmd>vs<cr>",
				mode = { "n" },
			},
			{
				"<c-s>",
				"<cmd>vs<cr>",
				mode = { "v" },
			},
			{ "<leader>i", mode = { "n" } },
			{ "<leader>i", mode = { "v" } },
			{ "<leader>o", mode = { "n" } },
			{ "<leader>o", mode = { "v" } },
			{ "<leader>O", mode = { "n" } },
			{ "<leader>O", mode = { "v" } },
			{
				"gt",
				mode = { "n" },
				"<cmd>call Sd_quick_align('up', 'n')<CR>",
			},
			{
				"gt",
				mode = { "v" },
				"<esc><cmd>call Sd_quick_align('up', 'v')<CR>",
			},
			{
				"gb",
				mode = { "n" },
				"<cmd>call Sd_quick_align('down', 'n')<CR>",
			},
			{
				"gb",
				mode = { "v" },
				"<esc><cmd>call Sd_quick_align('down', 'v')<CR>",
			},
			{
				"<leader><leader>F",
				mode = { "n" },
				"<cmd>call Sd_simple_format('n', 'n')<CR>",
			},
			{
				"<leader><leader>F",
				mode = { "v" },
				"<esc><cmd>call Sd_simple_format('v', 'n')<CR>",
			},
			{ "<leader>df", mode = { "n" } },
			{ "<leader>df", mode = { "v" } },
			{ "<leader><leader>df", mode = { "n" } },
			{ "<leader><leader>df", mode = { "v" } },
			{ "<leader>dg", mode = { "n" } },
			{ "<leader>dp", mode = { "n" } },
			-- { "<backspace>", "<cmd>call Sd_max_win_partially(1)<CR>", mode = { "n" } },
			{
				"<leader>sx",
				mode = { "n" },
				"<cmd>call Sd_open_vimrc()<CR>",
				desc = "open init.vim",
			},
			{ "<leader>sn", mode = { "n" } },
			{ "<leader>SN", mode = { "n" } },
			{ "<leader><leader>sn", mode = { "n" } },
			{ "<leader>sb", mode = { "n" } },
			{ "<leader>SB", mode = { "n" } },
			{ "<leader><leader>sb", mode = { "n" } },
			{
				"<leader><leader>v",
				mode = { "n" },
				function()
					vim.cmd("vsplit " .. vim.g.sd_template_dir .. "vim-note.txt")
				end,
				desc = "open note book",
			},
			{
				"RR",
				mode = { "n" },
				function()
					vim.cmd("normal! mp")
					vim.cmd("e!")
					vim.cmd("call Sd_set_shiftwidth()")
					vim.cmd("normal! `p")
				end,
			},
			{
				"<leader>c0",
				mode = { "n" },
				"V<esc><cmd>lua Sd_compress_whitespace(0)<CR>",
				desc = "compress whitespace (0)",
			},
			{
				"<leader>c0",
				mode = { "v" },
				"<esc><cmd>lua Sd_compress_whitespace(0)<CR>",
				desc = "compress whitespace (0)",
			},
			{
				"<leader>c1",
				mode = { "n" },
				"V<esc><cmd>lua Sd_compress_whitespace(1)<CR>",
				desc = "compress whitespace (1)",
			},
			{
				"<leader>c1",
				mode = { "v" },
				"<esc><cmd>lua Sd_compress_whitespace(1)<CR>",
				desc = "compress whitespace (1)",
			},
			{
				"<leader>c2",
				mode = { "n" },
				"V<esc><cmd>lua Sd_compress_whitespace(2)<CR>",
				desc = "compress whitespace (2)",
			},
			{
				"<leader>c2",
				mode = { "v" },
				"<esc><cmd>lua Sd_compress_whitespace(2)<CR>",
				desc = "compress whitespace (2)",
			},
			{
				"<leader>c3",
				mode = { "n" },
				"V<esc><cmd>lua Sd_compress_whitespace(3)<CR>",
				desc = "compress whitespace (3)",
			},
			{
				"<leader>c3",
				mode = { "v" },
				"<esc><cmd>lua Sd_compress_whitespace(3)<CR>",
				desc = "compress whitespace (3)",
			},
			{
				"<leader>c4",
				mode = { "n" },
				"V<esc><cmd>lua Sd_compress_whitespace(4)<CR>",
				desc = "compress whitespace (4)",
			},
			{
				"<leader>c4",
				mode = { "v" },
				"<esc><cmd>lua Sd_compress_whitespace(4)<CR>",
				desc = "compress whitespace (4)",
			},
		},
	},

	{
		"eandrju/cellular-automaton.nvim",
		config = function()
			vim.cmd("source ~/.config/nvim/very_lazy_sd_function.vim")
		end,
		init = function()
			if vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 then
				vim.g.sd_session_yank_file_remote = vim.fn.expand("$MYVIMRIDR/temp/") .. "vim_yank_remote"
				vim.g.sd_yank_paste_remote_bin = vim.g.sd_vim_dir .. "/portable_files/yank_paste_remote.py"
			else
				vim.g.sd_session_yank_file_remote = "/tmp/vim_yank_remote"
				vim.g.sd_yank_paste_remote_bin = vim.g.sd_vim_dir .. "/software/yank_paste_remote.py"
			end
		end,
		keys = {
			{
				"<leader>se",
				mode = { "n" },
				function()
					local current_win = vim.api.nvim_get_current_win()
					local height = vim.api.nvim_win_get_height(current_win)
					local width = vim.api.nvim_win_get_width(current_win)

					vim.api.nvim_command("wincmd x")

					local new_win = vim.api.nvim_get_current_win()
					vim.api.nvim_win_set_height(new_win, height)
					vim.api.nvim_win_set_width(new_win, width)
				end,
				desc = "In current window view, swap buffer, and keep winsize",
			},
			{
				"<leader>sw",
				mode = { "n" },
				function()
					vim.api.nvim_command("wincmd r")
				end,
				desc = "Exchange vim window position",
			},
			{
				"<localleader>yy",
				mode = { "v" },
				function()
					vim.api.nvim_command('normal! "py')
					local content = vim.fn.getreg("p", false)
					local file = io.open(vim.g.sd_session_yank_file_remote, "w")
					if file then
						file:write(content)
						file:close()
					else
						LazyVim.notify("Failed to open temporay file", {
							title = "yank to remote",
							level = 4,
						})
						return
					end
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -o yank -e viminfo -f "
						.. vim.g.sd_session_yank_file_remote
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("yank to remote viminfo succesfully!", {
							title = "yank to remote",
							level = 2,
						})
						return
					else
						LazyVim.notify("yank to remote viminfo failed!" .. result, {
							title = "yank to remote",
							level = 4,
						})
						return
					end
				end,
			},
			{
				"<localleader>yy",
				mode = { "n" },
				function()
					local current_line = vim.api.nvim_get_current_line()
					local file = io.open(vim.g.sd_session_yank_file_remote, "w")
					if file then
						file:write(current_line)
						file:close()
					else
						LazyVim.notify("Failed to open temporay file", {
							title = "yank to remote",
							level = 4,
						})
						return
					end
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -o yank -e viminfo -f "
						.. vim.g.sd_session_yank_file_remote
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("yank to remote viminfo succesfully!", {
							title = "yank to remote",
							level = 2,
						})
						return
					else
						LazyVim.notify("yank to remote viminfo failed!" .. result, {
							title = "yank to remote",
							level = 4,
						})
						return
					end
				end,
			},
			{
				"<localleader>yn",
				mode = { "v" },
				function()
					vim.api.nvim_command('normal! "py')
					local content = vim.fn.getreg("p", false)
					local file = io.open(vim.g.sd_session_yank_file_remote, "w")
					if file then
						file:write(content)
						file:close()
					else
						LazyVim.notify("Failed to open temporay file", {
							title = "yank to remote",
							level = 4,
						})
						return
					end
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -o yank -e noteboard -f "
						.. vim.g.sd_session_yank_file_remote
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("yank to remote noteboard succesfully!", {
							title = "yank to remote noteboard",
							level = 2,
						})
						return
					else
						LazyVim.notify("yank to remote noteboard failed!" .. result, {
							title = "yank to remote noteboard",
							level = 4,
						})
						return
					end
				end,
			},
			{
				"<localleader>yn",
				mode = { "n" },
				function()
					local current_line = vim.api.nvim_get_current_line()
					local file = io.open(vim.g.sd_session_yank_file_remote, "w")
					if file then
						file:write(current_line)
						file:close()
					else
						LazyVim.notify("Failed to open temporay file", {
							title = "yank to remote",
							level = 4,
						})
						return
					end
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -o yank -e noteboard -f "
						.. vim.g.sd_session_yank_file_remote
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("yank to remote noteboard succesfully!", {
							title = "yank to remote noteboard",
							level = 2,
						})
					else
						LazyVim.notify("yank to remote noteboard failed!" .. result, {
							title = "yank to remote noteboard",
							level = 4,
						})
					end
				end,
			},
			{
				"<localleader>pn",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e noteboard -o paste -c 99999"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"QP1",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e noteboard -o paste -c 99998"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"QP2",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e noteboard -o paste -c 99997"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"QP3",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e noteboard -o paste -c 99997"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"QP4",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e noteboard -o paste -c 99996"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"<localleader>pp",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e viminfo -o paste -c 9999"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"<localleader>p1",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e viminfo -o paste -c 9998"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"<localleader>p2",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e viminfo -o paste -c 9997"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"<localleader>p3",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e viminfo -o paste -c 9996"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},
			{
				"<localleader>p4",
				mode = { "n" },
				function()
					local command = vim.g.python3_host_prog
						.. " "
						.. vim.g.sd_yank_paste_remote_bin
						.. " -e viminfo -o paste -c 9995"
					local result = vim.fn.system(command)
					local exit_status = vim.v.shell_error
					if exit_status == 0 then
						LazyVim.notify("paste from remote succesfully!", {
							title = "paste from remote",
							level = 2,
						})
					else
						LazyVim.notify("paste from remote failed!" .. result, {
							title = "paste from remote",
							level = 4,
						})
						return
					end
					vim.fn.setreg("p", result)
					vim.api.nvim_command('normal! "pp')
				end,
			},

			{
				"[[",
				mode = { "n", "x" },
				function()
					-- line("w0")
					-- line("w$")
					if vim.bo.filetype == "python" then
						vim.fn.search(
							"^\\s*\\(function\\|if __name__\\|class\\|def\\|async def\\)\\s\\+.",
							"bWe",
							0,
							800
						)
					elseif vim.bo.filetype == "go" then
						-- vim.fn.search("^\\(\\s*func\\|type\\|var\\|import\\)\\s\\+.", "bWe", 0, 800)
						vim.fn.search(
							"^\\(\\s*func\\|\\s*func\\s\\S\\+\\s\\S\\+\\|\\s\\+go\\|type\\|var\\|import\\)\\s\\+\\(_\\|\\w\\)",
							"bWe",
							0,
							800
						)
					else
						vim.api.nvim_command("normal! 0")
						vim.fn.search("\\(^\\s*\\n\\s*\\|\\%^\\)\\@<=\\S\\+", "bW", 0, 800)
					end
				end,
				desc = "jump upwards",
			},
			{
				"]]",
				mode = { "n", "x" },
				function()
					if vim.bo.filetype == "python" then
						vim.fn.search(
							"^\\s*\\(function\\|if __name__\\|class\\|def\\|async def\\)\\s\\+.",
							"We",
							0,
							800
						)
					elseif vim.bo.filetype == "go" then
						-- vim.fn.search("^\\(\\s*func\\|type\\|var\\|import\\)\\s\\+.", "We", 0, 800)
						vim.fn.search(
							"^\\(\\s*func\\|\\s*func\\s\\S\\+\\s\\S\\+\\|\\s\\+go\\|type\\|var\\|import\\)\\s\\+\\(_\\|\\w\\)",
							"We",
							0,
							800
						)
					else
						vim.api.nvim_command("normal! $")
						vim.fn.search("\\(^\\s*\\n\\s*\\)\\@<=\\S\\+", "W", 0, 800)
					end
				end,
				desc = "jump downwards",
			},
			{
				"!!",
				mode = { "n" },
				function()
					local current_line = vim.api.nvim_get_current_line()
					local file_dir = vim.fn.expand("%:p:h")
					local result = vim.fn.system("cd " .. file_dir .. " &&  timeout 8 " .. current_line)
					local exit_status = vim.v.shell_error

					local log_level = 2
					if exit_status == 0 then
						if result:match("^%s*$") ~= nil then
							LazyVim.notify("Command exit status " .. exit_status .. ". Empty output", {
								title = "Run shell Command",
								level = log_level,
							})
							return
						end
					else
						if result:match("^%s*$") ~= nil then
							LazyVim.notify("Command exit status " .. exit_status .. ". Empty output", {
								title = "Run shell Command",
								level = 4,
							})
							return
						end
					end

					vim.fn.setreg("p", result, "l")

					vim.api.nvim_command('normal! "pp')

					LazyVim.notify("Command exit status " .. exit_status, {
						title = "Run shell Command",
						level = log_level,
					})
				end,
			},
			{
				"!!",
				mode = { "v" },
				function()
					vim.api.nvim_command('normal! "py')
					local command = vim.fn.getreg("p", false)
					local file_dir = vim.fn.expand("%:p:h")
					local file = io.open("/tmp/vim_run_shell_cmd", "w")
					if file then
						file:write("#!/usr/bin/env bash\n\nset -eu\n\ncd " .. file_dir .. "\n\n")
						file:write(command)
						file:close()
					else
						LazyVim.notify("Failed to prepare run-cmd script file", {
							title = "Run shell Command",
							level = 4,
						})
					end
					local result = vim.fn.system("timeout 8 bash /tmp/vim_run_shell_cmd")
					local exit_status = vim.v.shell_error

					local log_level = 2
					if exit_status == 0 then
						if result:match("^%s*$") ~= nil then
							LazyVim.notify("Command exit status " .. exit_status .. ". Empty output", {
								title = "Run shell Command",
								level = log_level,
							})
							return
						end
					else
						log_level = 4
						if result:match("^%s*$") ~= nil then
							LazyVim.notify("Command exit status " .. exit_status .. ". Empty output", {
								title = "Run shell Command",
								level = log_level,
							})
							return
						end
					end

					-- vim.fn.setreg("p", result)
					vim.fn.setreg("p", result, "l")

					local bufnr = vim.api.nvim_get_current_buf()
					local start_pos = vim.api.nvim_buf_get_mark(bufnr, "<") -- start of selection
					local end_pos = vim.api.nvim_buf_get_mark(bufnr, ">") -- end of selection
					if start_pos[1] ~= 0 and end_pos[1] ~= 0 then
						vim.api.nvim_win_set_cursor(0, { end_pos[1], end_pos[2] }) -- `0` refers to the current window
						-- else
						--  print("No virtual selection found.")
					end

					vim.api.nvim_command('normal! "pp')
					LazyVim.notify("Command exit status " .. exit_status, {
						title = "Run shell Command",
						level = log_level,
					})
				end,
			},
			{
				"QNN",
				function()
					vim.cmd("set foldlevel=99")
					vim.cmd("CellularAutomaton make_it_rain")
				end,
				mode = { "n" },
			},
			-- comment line 01
			{ "<localleader>m", mode = { "n" } },
			-- comment line 02
			{ "<localleader>N", mode = { "n" } },
			{ "<localleader>N", mode = { "v" } },
			-- comment triple lines
			{ "<localleader>n", mode = { "n" } },
			-- manually comment
			{ "<leader>ca", mode = { "n" } },
			{ "<leader>ca", mode = { "v" } },
			{ "<leader>cv", mode = { "n" } },
			{ "<leader>cv", mode = { "v" } },
			{ "<leader>cm", mode = { "n" } },
			{ "<leader>cm", mode = { "v" } },
			{ "<leader>cc", mode = { "n" } },
			{ "<leader>cc", mode = { "v" } },
			{ "<leader>c-", mode = { "n" } },
			{ "<leader>c-", mode = { "v" } },
			{ "<leader>ch", mode = { "n" } },
			{ "<leader>ch", mode = { "v" } },
			-- quick insert/delete line number
			{ "<leader><leader>0", mode = { "v" } },
			{ "<leader><leader>-", mode = { "v" } },
			{ "<leader><leader>=", mode = { "v" } },
			{ "\\", mode = { "n" } },
			{ "'", mode = { "n" } },
			{ "'", mode = { "v" } },
			{ "<leader><", mode = { "n" } },
			{ "<leader><", mode = { "v" } },
			{ "<space>c", mode = { "n" } },
			{ "<leader>DF", mode = { "n" } },
			{ "<leader>DD", mode = { "n" } },
			{ "<leader>ci", mode = { "n" } },
			{ "<leader>ci", mode = { "v" } },
			{ "QB", mode = { "n" } },
			{ "Qb", mode = { "n" } },
			-- { "QD",                 mode = { "n" }},
			{ "QA", mode = { "n" } },
			{ "<leader>cm", mode = { "n" } },
			{ "<leader>cm", mode = { "v" } },
			{ "<leader>cm", mode = { "i" } },
			{ "<leader>bp", mode = { "n" } },
			{ "*", mode = { "n" } },
			{ "<leader>*", mode = { "n" } },
			{ "<leader>c<cr>", mode = { "n" } },
			{ "<leader>c<cr>", mode = { "v" } },
		},
	},
}
